Skip to content

Latest commit

 

History

History
182 lines (156 loc) · 12 KB

permissions.md

File metadata and controls

182 lines (156 loc) · 12 KB

Tenancy — Permission Matrix

Per Permission Standards, which names this file. Part of the module spec.

P02b-5 account-site subject. GetAccountSiteQuery is non-public and explicitly audit Off. It adds no permission key or grant, and returns only the context's own actor/scope with the existing public site projection. Its implemented HostAndClaim/host-scope guard precedes all readers; membership alone cannot admit it. The module contract owns the boundary. P02b-5 Step 4 exposes only its authenticated GET route; Accepted ADR-0076 adds live membership/lifecycle checks to its protected admission while preserving its independent host ceiling and Off success classification. The Phase 03 Status block owns execution and qualification; acceptance is not activation.

ADR-0078 additionally admits the separately validated native-session origin under the same real-host ceiling. It does not admit HostOnly/ClaimAndMembership or turn AccountSite into an admin query; qualification lives in the phase Status block above.

P02b-1 Step 3 producer implemented — 2026-10-12. The completed-provisioning domain translator runs only during owner completion, adds no endpoint or permission, and inserts a pending outbox row under the provisioning announcement. Existing command reachability is unchanged. The integration-event catalogue owns the flow.

ADR-0046 P02b-2 complete and merged — 2026-10-13. All four steps completed both independent review rounds. The merge closeout owns CI/merge status. The API-owned dispatcher and terminal audit add no permission key or HTTP endpoint. P02b-3's targeted replay is internal; Phase 03 separately decides operator permission and routes. Neither grants a tenant administrator bypass-role access.

P02d-4 Step 2 implemented — 2026-10-03. Both review rounds and focused fix verification pass. Site bootstrap is a marked GET/HEAD request, audit Off and without a permission key or grant. It uses matching host scope and READ ONLY; normal reads add no audit row. Public configuration/settings ports remain internal and unrouted. Independent rejected- assertion auditing remains unchanged. The public contract owns allowlisting and lifecycle/locale checks.

Accepted ADR-0076 classifies that existing bootstrap through virtual Tenant tenancy.public_site.read. This is Portal Public policy metadata, unavailable as a stored Role grant; it adds no endpoint, Membership, template or visibility. Credential-free public reads perform no identity/grant lookup. The Permission standard owns the virtual class.

P02d-3 Step 1 implemented — 2026-10-02; both review rounds passed. ITenantSettingsAccessor is internal and unrouted, uses trusted ambient scope and adds no HTTP endpoint or permission key. Public admission belongs to P02d-4. The module contract owns its scope.

P02d-2 Step 2 writers — 2026-10-02. The locale and branding commands are implemented unrouted tenant-wide operations, with no assignable permission or organization override. Their finite Seed admission is described below. Human-facing permissions bind the separate human handlers below. Their transport qualification belongs to Phase 03. No additional Hub-internal route is admitted here.

Bounded assignable contract. ADR-0079 selects exactly the three Tenant pairs below. The versioned manifest owns first adoption into Tenant Admin; declaration alone grants nothing. No Organization Tenancy pair or generic settings power is selected. The virtual Portal Public definition above remains nonassignable and separate.

Six write handlers and four verification queries have finite Seed admission. TenancyOperationPolicySource binds each request to its declared Seed source under the live contract. The verification queries remain audit Off. These bindings add no HTTP or Hub-internal route and no assignable permission key.

ProvisionTenantCommand runs with an unresolved tenant context so it can announce the tenant it creates. Provisioning precedes Membership and attributes the write to UserId.SystemActor; that value supplies no exemption from the finite source/request gate.

CreateOrganizationCommand, MapHostToTenantCommand and the three P02d-2 writers run resolved and derive their tenant from context, never request input. Finite source admission and database isolation independently constrain these writes. The Seeder remains their production caller. Phase 02c owns the planned Hub-internal routes: tenant creation invokes ProvisionTenantCommand, which also creates the default organization, and host mapping invokes MapHostToTenantCommand. It adds no direct CreateOrganizationCommand endpoint. That future surface accepts only learnstack-hub realm tokens and needs its own admitted operation policy.

A future host-mapping route requires its own admission decision. MapHostToTenantCommand controls whose data an anonymous request sees. The proposed tenancy.hostmapping.admin key therefore describes an admin-scope act, outside ordinary tenant-admin grants; HostMapping has no write action. The proposed tenancy.tenant.admin remains a future provisioning example, not a P03-3 grant. The older unregistered tenancy.organization.write example is replaced for this packet by Tenant tenancy.organization.admin, covering lifecycle/default acts. P03-3 creates no human host-mapping, domain, feature-flag or platform-operator authority. Their named Phase 02c/P03-9 surfaces retain separate admission decisions.

Resource read write delete admin Default role grants
Organization (organization) – – – Tenant Exact v2 Tenant Admin delta; only admitted Organization/default operations
TenantLocale (locale) – Tenant – – Same delta; only admitted locale operations through Tenant root
TenantSetting (setting) – Tenant – – Same delta; whole tenant-wide branding.theme plus ADR-0093's exact invitation policy

Tenant has no delete: deprovisioning has no owning phase, and Database Standards § GRANT matrix records that the widening it needs is an ADR's to make, not a migration's.

Bounded human administration contract

Internal human requests carry separate Protected policies and audit bindings. Phase 03 owns packet state and transport qualification. All human writes require current Tenant capability, exact orgless context and fresh target/delegation/version checks under the canonical fences. The Tenant comes from resolved context; OrganizationId is a resource selector, not authority. Org Admin receives none of these three pairs. Its own-organization settings and Organization editor capabilities require a separate Phase 06 decision/consumer.

Human request Exact Tenant capability Root
ListOrganizationsQuery tenancy.organization.admin Detached bounded page; current Tenant default/version metadata
GetOrganizationDetailQuery Same Detached Organization and current default association
ReadOrganizationReceiptQuery tenancy.organization.admin Exact original retained Organization; Scoped ordinary ReadWrite with fresh MUST disclosure audit, no original mutation rerun
ReadDefaultOrganizationReceiptQuery Same Original Tenant default-outcome resource, not the selected Organization; current disclosure capability and MUST read audit
CreateManagedOrganizationCommand tenancy.organization.admin Organization
RenameOrganizationCommand Same Organization
ArchiveOrganizationCommand Same Organization
SelectDefaultOrganizationCommand Same Tenant; Active/nondeleted selected Organization must belong to it
AddManagedTenantLocaleCommand tenancy.locale.write Tenant
SetManagedDefaultTenantLocaleCommand Same Tenant
SetTenantLocaleEnabledCommand Same Tenant
RemoveTenantLocaleCommand Same Tenant
SetManagedTenantBrandingCommand tenancy.setting.write TenantSetting

These requests share module business logic with the existing Seed acts without dispatching them or obtaining Seed provenance. TenancyOperationPolicySource classifies each human request separately; audit owns the exact event/class bindings. Organization reads require the same Tenant administration capability and MUST configuration-read audit; reads do not imply an orgless mutation. Receipt reads permit terminal target facts only for their original outcome, leaving ordinary list/detail filters unchanged. Default selection writes only Tenant's reference/version, not the target Organization. Locale writes capture Tenant's contained navigation.

The new AdoptSeedAdministrationOriginCommand is instead a closed Seed-only act, one Tenant per invocation. It cannot be sent by a human wrapper or obtained from the v2 grant. Its fixed mapping projection and Tenant marker share the announced unit of work and two MUST intents. No general host-mapping route or permission is introduced. The module contract and Standard 05 own exact witness/adoption/fence rules and write-free repeats.

Invitation lifetime policy

Derives from: ADR-0093. This Accepted extension adds the exact tenant-wide identity.invitation.ttl_days setting operation to existing Tenant tenancy.setting.write; runtime/proof remain P03-4 in the phase Status block. Existing holders gain this bounded operation. No new pair, release, automatic grant or generic settings power is introduced. A v1 tenant without the pair uses the 14-day default but cannot edit; the explicit v2 adoption remains the only exceptional new-key grant path.

Application consumer Exact authority Root / audit
GetTenantInvitationPolicyQuery Own-current-tenant Membership coverage, orgless context Only default/current bounded lifetime and absent/default or root version precondition; Off and physical ReadOnly
SetTenantInvitationLifetimeCommand Tenant tenancy.setting.write, orgless context, fresh target/version checks One TenantSetting root, fixed key, integer 1–30 days; MUST update and protected keyed receipt
ReadInvitationPolicyReceiptQuery Current own-Membership coverage in the same orgless tenant Exact original retained TenantSetting ID/key; MUST read, no old write-permission requirement or other-setting disclosure

First creation requires the explicit absent/default precondition and natural-key uniqueness; a race refuses, never becomes an unconditional upsert. Later writes require canonical strong If-Match. Policy changes do not extend prepared links; each initial send or explicit reissue freezes its current policy expiry. Read contracts supply no arbitrary setting directory or Organization setting variant. Identity consumes the bounded policy through Tenancy's application contract, never direct Tenancy SQL. Standard 19 owns grant adoption semantics and the API standard owns exact transport/replay consumers.