11

Share and Revoke Without Leaking Authority

Let a customer share one generated application without confusing platform membership, runtime identity, and application access.

Run it in the public monorepo

This course is built around the public Zheta Kubernetes Lab monorepo. The excerpt below is runnable source, not pseudocode.

Source: services/control_plane/domain.py

def retire(self, project: Project, actor: str) -> None:
        self._owner(project, actor)
        project.status = "retired"
        with self.repository.transaction():
            self.repository.save(project)
            self._audit(project, actor, "project.retired")
        self.runtime.delete(project.organization_id, project.project_id)

    def delete(self, project: Project, actor: str) -> None:
        self._owner(project, actor)
        if project.status != "retired":
            raise ValueError("retire project before deletion")

Code to reality

Declared intent
Enforce the product lifecycle so published runtime state is retired before durable deletion.
Interpreter
The injected Forge model applies ownership and state-machine rules independently of HTTP or storage technology.
Software effect
Retirement removes the hosted runtime and records status before deletion can tombstone control-plane state.
Hardware effect
Runtime containers and storage can be released in order while retained evidence remains physically durable.
Observable evidence
A denied early delete, successful retirement, absent runtime, tombstoned project, and retained audit event prove order.

Start with the people and the result they need

The source tables below remain the detailed contract. Begin with these customer paths:

  • D11-UC-01
    • Person: Workspace owner
    • Job: Share one Research Brief, Service Desk, or Field Inspection application with a named collaborator
    • Observable result: Collaborator opens only the granted application and sees only authorised generated-application data
  • D11-UC-02
    • Person: Organization administrator
    • Job: Revoke a collaborator without disabling the application for its owner
    • Observable result: Existing collaborator sessions stop authorising new requests and the owner path remains healthy

Turn each customer job into a testable story

Now turn each customer job into a story with a result that an engineer can check:

  • D11-US-01
    • Story: As a workspace owner, I want to grant a collaborator a named application role, so that they can use one application without inheriting my workspace…
    • Observable acceptance: Grant names application, tenant, role, expiry, grantor, grantee, environment, and trace; positive and outsider probes are recorded
  • D11-US-02
    • Story: As an organization administrator, I want to revoke one grant independently, so that access ends without an application outage
    • Observable acceptance: New requests using the revoked grant are denied, cached sessions expire or are invalidated, and an owner positive control still passes

Add real state and observable proof

Finally trace each story through the system that owns its state and the evidence that proves the outcome:

  • D11-FLOW-01
    • Trigger: Owner selects Share, collaborator, role, and expiry
    • Responsible systems: Control-plane authorization, Grant Service, Runtime Session Gateway, generated-app Policy Evaluator
    • Authoritative state: Grant Service database for cross-plane mapping; generated-app database for roles and tenant predicates
    • Owned record: ApplicationGrant
    • Observable evidence: Allowed and denied results with actor, application, tenant, scope, precondition, expected and observed result, environment, timestamp, grant ID, and…
    • Failure signal: Unknown grantee, cross-tenant role request, expired grant, or outsider denial trace
  • D11-FLOW-02
    • Trigger: Administrator selects Revoke access
    • Responsible systems: Grant Service, invalidation stream, Runtime Session Gateway, generated-app Policy Evaluator
    • Authoritative state: Grant Service database for grant status and revocation time
    • Owned record: AppRoleBinding
    • Observable evidence: Revocation record, denied former collaborator trace, owner response trace, environment, timestamp, and immutable run ID
    • Failure signal: Stale session accepted after cutoff, missing invalidation acknowledgement, or owner control failure

The enterprise problem and today’s slice

Enterprise problem: A workspace owner needs to share a Zheta Forge application, but copying a URL or reusing workspace membership can expose another tenant’s data and leave no reliable way to revoke access. Whole-course context: The current platform has provider identity, project state, artifact preview, and connector metadata; today adds a named provider collaborator. Today’s slice: We implement and test provider-plane share/revoke while preserving separate hosted-runtime and generated-app grant designs that do not yet exist in code. End-of-day evidence: Durable collaborator state, owner-only mutation, revoked-collaborator denial, unaffected owner access, and share/revoke audit actions prove the implemented boundary. Still unsolved: App-local roles, expiry, session invalidation, immutable publication, public release policy, and rollback remain deferred.

Customer use cases

Sharing fails dangerously when “can open the URL” is mistaken for “may read this tenant’s records,” so each grant needs an explicit actor, resource, scope, and expiry. These use cases cover both access and its independent removal.

Use case IDActorCustomer jobSuccess outcomeDenial or recovery evidence
D11-UC-01Workspace ownerShare one Research Brief, Service Desk, or Field Inspection application with a named collaboratorCollaborator opens only the granted application and sees only authorised generated-application dataAn ungranted user receives a recorded denial while the owner remains able to open the application
D11-UC-02Organization administratorRevoke a collaborator without disabling the application for its ownerExisting collaborator sessions stop authorising new requests and the owner path remains healthyRevocation trace identifies the grant and session cutoff; repeated revocation is harmless and auditable

Actor-centred user stories

A share button is incomplete if nobody can state what it authorises or how denial is observed. These stories bind the customer action to positive and negative outcomes.

Story IDUse case IDsUser storyObservable acceptance conditions
D11-US-01D11-UC-01As a workspace owner, I want to grant a collaborator a named application role, so that they can use one application without inheriting my workspace authorityGrant names application, tenant, role, expiry, grantor, grantee, environment, and trace; positive and outsider probes are recorded
D11-US-02D11-UC-02As an organization administrator, I want to revoke one grant independently, so that access ends without an application outageNew requests using the revoked grant are denied, cached sessions expire or are invalidated, and an owner positive control still passes

End-to-end product flows

Access decisions become untrustworthy when the product cannot reconstruct how a click became a generated-application permission. The flows begin at customer-visible share and revoke actions and end in observed evidence.

Flow IDUse case IDsPathTriggerNumbered stepsTerminal evidence
D11-FLOW-01D11-UC-01HappyOwner selects Share, collaborator, role, and expiry1. Control plane verifies grantor authority. 2. Grant service creates an application-scoped grant. 3. Runtime exchanges it for a short session. 4. Generated application evaluates tenant and role predicates. 5. Test the collaborator and outsider paths.Allowed and denied results with actor, application, tenant, scope, precondition, expected and observed result, environment, timestamp, grant ID, and trace IDs
D11-FLOW-02D11-UC-02RecoveryAdministrator selects Revoke access1. Mark the exact grant revoked. 2. Publish a session-invalidation event. 3. Reject later requests carrying that grant. 4. Probe the owner as an unaffected positive control.Revocation record, denied former collaborator trace, owner response trace, environment, timestamp, and immutable run ID

The owner acts on one application, and the named collaborator is the intended recipient. No organization, workspace, or application role is silently copied by this path.

System design derived from the flows

One identity token cannot safely cross all three planes because each plane owns different resources and revocation rules. An explicit grant service maps opaque identifiers while each boundary still performs its own authorization.

Use case IDEntry pointResponsible servicesAuthoritative storeFailure evidence
D11-UC-01Control-plane Share actionControl-plane authorization, Grant Service, Runtime Session Gateway, generated-app Policy EvaluatorGrant Service database for cross-plane mapping; generated-app database for roles and tenant predicatesUnknown grantee, cross-tenant role request, expired grant, or outsider denial trace
D11-UC-02Control-plane Revoke actionGrant Service, invalidation stream, Runtime Session Gateway, generated-app Policy EvaluatorGrant Service database for grant status and revocation timeStale session accepted after cutoff, missing invalidation acknowledgement, or owner control failure

The Grant Service owns the provider mapping, the Session Gateway owns runtime sessions, and the Policy Evaluator owns the final generated-application decision. Their identifiers are opaque references, not inherited authority, and each mapping is least-privilege, audited, and independently revocable.

Data model and ownership

Revocation cannot be proven from an audit message alone because the durable grant and generated-app role must retain separate owners. The model records their relationship without moving domain data into the control plane.

Generated-application database: Not created in this runnable slice — the current model owns provider project collaborators only; generated-app tenant roles, visibility predicates, sessions, and domain authorization remain a separate target boundary.

Record or entityStore and ownerPrimary keyForeign key or opaque referenceTenant keyMaterial constraintLifecycle and deletionUse case IDs
ApplicationGrantControl-plane Grant Store, owned by Grant Servicegrant_idOpaque application_release_id and generated_app_subject_reforganization_idOne active grant per grantee, application, role, and scope; revoked grants cannot reactivateCreate, expire or revoke, retain for audit, then tombstone by policyD11-UC-01, D11-UC-02
AppRoleBindingGenerated-application database, owned by Policy Evaluatorrole_binding_idOpaque grant_id; no control-plane foreign keyapp_tenant_idSubject must belong to tenant and role must be declared by this applicationCreate from valid mapping, disable on revocation, export with tenant, delete with application retention policyD11-UC-01, D11-UC-02
RuntimeSessionRuntime session store, owned by Session Gatewaysession_idOpaque grant_id and role_binding_idruntime_tenant_idExpiry and revocation cutoff are checked on every privileged requestIssue, rotate, invalidate, expire quickly, delete after security retentionD11-UC-01, D11-UC-02

The durable grant moves from active to expired or revoked, after which runtime and application checks deny it. The paired positive and negative traces prove revocation without mistaking a broad outage for correct authorization.

Run the grant evidence loop

A configuration that looks scoped can still be implemented as a permissive check, so exercise both sides of the boundary. The current Python model implements owner-controlled provider collaboration, including the rule that the owner cannot be revoked; it has no generated-app role, expiry, or session service. Read the exact methods in services/control_plane/domain.py.

def share(self, project: Project, actor: str, collaborator: str) -> None:
    self._owner(project, actor)
    project.collaborators.add(collaborator)
    self._save_and_audit(project, actor, "collaborator.shared")

def revoke(self, project: Project, actor: str, collaborator: str) -> None:
    self._owner(project, actor)
    if collaborator == project.owner:
        raise ValueError("owner cannot be revoked")
    project.collaborators.discard(collaborator)
    self._save_and_audit(project, actor, "collaborator.revoked")
Effect fieldWhat happens
Declared intentOnly the project owner can add or remove one provider-plane collaborator, and the owner remains non-revocable
InterpreterPython executes Forge.share or Forge.revoke; injected repository and event ports own persistence and evidence
Software effectThe collaborator set is saved and collaborator.shared or collaborator.revoked is published; no role, expiry, or app session changes
Hardware effectThe control-plane process consumes CPU and local SQLite/broker paths consume storage and networking
EvidenceAuthenticated HTTP response, restored collaborator set, collaborator denial after revoke, owner positive control, and audit action

Key takeaways

Sharing is an explicit, revocable mapping among three independently authorised planes, not a copied URL or inherited role.

  • Provider membership does not grant runtime or generated-application access.
  • Revocation needs a negative probe and an unaffected positive control.
  • Opaque references connect owners without transferring ownership.

Checklist

An access change is complete only when its scope and removal are observable.

  • [ ] Grant names application, tenant, role, subject, grantor, and expiry
  • [ ] Outsider denial and collaborator allowance are recorded
  • [ ] Revocation invalidates future requests without disabling the owner
  • [ ] Evidence contains actor, resource, scope, environment, time, run, and trace IDs