Revocation, Audit, and Observability
Source: How Enterprise Authentication and Authorization Work in an Agent Platform, sections 30 and 35; preserves the generated-application revocation model migrated from the former Sharing, Roles, and Revocation lesson.
The enterprise problem and today’s slice
Enterprise problem: Removing a user or connector in an admin screen does not stop cached decisions, live sessions, subscriptions, signed URLs, child agents, or queued jobs, and fragmented logs cannot prove when access actually ended.
Whole-course context: The incoming evidence is an immutable deployment with separate provider grants, workload/network controls, generated-app roles, and per-call decision IDs; today makes changes to that authority converge measurably.
Today’s slice: We design versioned revocation, immediate high-risk rechecks, cancellation propagation, cross-boundary lineage, redacted audit events, metrics, and security-information-and-event-management export across all three authorization planes.
End-of-day evidence: A revocation run records the request time, first confirmed denial, every convergence leg, unaffected positive controls, residual limits, complete actor chain, policy versions, and immutable trace and event identifiers.
Still unsolved: The adversarial threat suite, release-blocking acceptance thresholds, staged production rollout, rollback drills, and final retirement evidence remain deferred.
Customer use cases
A revoked grant can remain effective through many independently cached paths, so a database update is not the customer outcome. These use cases require observed convergence and an audit narrative that an investigator can reconstruct without exposing secrets.
| Use case ID | Actor | Customer job | Success outcome | Denial or recovery evidence |
|---|---|---|---|---|
| D11-UC-01 | Enterprise security administrator | Revoke a provider project member, preview link, generated-app audience grant, connector, deployment, approval, or entire app during active work | Every controllable cache, session, stream, signed URL, run, child run, and queued side effect reaches the target denial within its stated objective while unrelated grants stay active | Per-leg probes capture request and first-denial times, stale-version rejects, cancellations, unaffected positive controls, and honest statements that downloads and screenshots cannot be recalled |
| D11-UC-02 | Security operations investigator | Reconstruct an authorization incident from app request through provider decision, runtime, tool gateway, connector, and downstream result | One redacted lineage joins session, run, model, retrieval, intent, decision, approval, protocol, downstream, and child-run identifiers and exports to the enterprise SIEM | Missing-lineage, late-event, and secret-canary checks alert; denied and successful controls remain distinguishable without raw prompts, tokens, cookies, or document bodies |
Authorization freshness is risk-based. Low-risk reads use short run tokens, periodic membership revalidation, and bounded policy caches. High-risk writes recheck current membership, deployment status, connector state, approval state, app grant version, and exact argument digest immediately before execution, then obtain a fresh downstream token.
Actor-centred user stories
“Revoked” and “audited” are not observable unless the actor can see which path stopped, when it stopped, and which authority deliberately survived. The stories define measurable evidence instead of promising impossible instantaneous recall.
| Story ID | Use case IDs | User story | Observable acceptance conditions |
|---|---|---|---|
| D11-US-01 | D11-UC-01 | As a security administrator, I want each authority removed independently and propagated through every controllable delivery path, so that a stale session or job cannot keep acting and unrelated access is not destroyed | Evidence names authoritative target and version; cache invalidation, session termination or recheck, stream closure, signed-URL expiry, parent/child cancellation, and job cancellation status; request time and first confirmed denial; unaffected grant probes; and residual downloaded-byte limits |
| D11-US-02 | D11-UC-02 | As a security operations investigator, I want every allow, deny, approval, credential resolution, and downstream result joined by stable lineage, so that I can explain an incident without collecting secrets | A query from app session_id reaches parent and child run_id, tool intent, decision, approval, MCP request, connector request, and downstream request; actor chain and policy digest are present; a secret canary is absent; missing links and staleness breach generate alerts |
The administrator chooses a specific revocation target rather than a generic “remove access” operation. Provider project membership, revision-bound preview capability, generated-app audience grant, app visibility policy, connector instance, agent deployment, and one approval are different records with different caches and residual effects. One target can be removed while the others remain positive controls.
Generated-app access is evaluated at every protected request using current visibility, authenticated principal or capability, tenant membership, role, resource, and action. A short-lived cache key includes app ID, tenant ID, principal ID, policy version, membership version, visibility version, grant version, and action, so a version advance makes stale entries unusable. Subscriptions reauthorize on connect, reconnect, policy change, and a bounded heartbeat. Background jobs carry tenant, initiating principal, grant/policy versions, and exact intended side effect, then reauthorize before execution. Signed object URLs are short-lived and tenant-scoped; search indexes, exports, analytics, and notifications preserve the originating tenant and audience boundary.
End-to-end product flows
A final 403 does not show whether an old stream or queued write survived, so the product flow must probe all paths from a known authorized precondition. A monotonic version is a number that only increases; embedding it in caches and jobs makes an older grant detectably stale rather than silently reusable.
| Flow ID | Use case IDs | Path | Trigger | Numbered steps | Terminal evidence |
|---|---|---|---|---|---|
| D11-FLOW-01 | D11-UC-01 | Recovery | Security administrator removes a Finance analyst from the team during an agent run | 1. Product verifies the current membership and active parent/child runs, then records the authorized precondition.<br>2. Membership service disables the grant, increments membership_version, and appends a revocation request.<br>3. Transactional outbox publishes a versioned event to authorization caches, provider sessions, runtime supervisors, app session indexes, stream controllers, signed-URL service, and job queues.<br>4. Parent and child runs cancel; the next privileged action revalidates and denies; no fresh capability token or credential is issued.<br>5. Generated app closes affected subscriptions and forces current role/membership evaluation while leaving a different app grant active.<br>6. Probe runner polls every leg until denial or the declared deadline. | Actor secadmin_7, user and membership resources, revoked team/run/tool scopes, authorized precondition, expected denial objectives, observed per-leg status and first-denial times, unaffected app-grant result, environment, timestamps, event offset, revocation run ID, decision IDs, and trace IDs |
| D11-FLOW-02 | D11-UC-01 | Denied | A queued high-risk Slack post reaches execution after its approval or connector was revoked | 1. Job presents captured tenant, principal, deployment, app grant, approval version, connector version, and argument digest.<br>2. Tool gateway immediately reloads current high-risk state.<br>3. Version or digest mismatch denies before credential resolution.<br>4. Job records terminal cancellation and cannot retry with stale authority.<br>5. A separately approved read uses current state as a positive control. | Actor, message/channel resource, slack.post_message scope, stale approval/connector precondition, expected deny, observed broker-not-called and job-cancelled results, positive control, environment, timestamp, decision ID, and immutable job attempt ID |
| D11-FLOW-03 | D11-UC-02 | Happy | Investigator opens an authorization incident by application trace ID | 1. Evidence service resolves app session and request to provider run without trusting the app as policy authority.<br>2. It joins model and retrieval requests, tool intent, authorization decision, approval, capability-token hash, protocol request, connector request, downstream request, and child-agent lineage.<br>3. It displays subject, actor, organization, active team, app tenant, deployment, tool, constrained resource, policy digest, credential mode, result, and duration.<br>4. Redaction removes prompts, raw documents, tokens, keys, cookies, and sensitive results.<br>5. Export service signs and sends the bounded event set to the customer SIEM. | Actor/investigator, incident resource, audit-read scope, immutable-event precondition, expected complete redacted chain, observed lineage completeness and export acknowledgment, production environment, timestamps, query ID, event IDs, and signed export batch ID |
| D11-FLOW-04 | D11-UC-02 | Failure | Audit completeness monitor finds a tool result with no authorization-decision link or detects a secret canary | 1. Stream processor compares required lineage edges and redaction patterns.<br>2. It quarantines the export batch and emits severity based on operation risk.<br>3. Supervisor marks the affected evidence interval incomplete and identifies producer and last valid offset.<br>4. Repair replays immutable events, never fabricating a decision.<br>5. Completeness and canary probes rerun before export resumes. | Actor/service, affected event interval, audit-export scope, expected complete/redacted precondition, observed missing edge or canary hash, quarantine and recovery status, environment, timestamp, source offsets, replay run ID, and alert ID |
A self-contained token can remain usable until expiry unless an online check or denylist exists, so the product publishes separate objectives for low-risk cache freshness, privileged action revalidation, stream closure, and job cancellation. Public anonymous access cannot be revoked per person, and already downloaded, exported, copied, or screenshotted bytes cannot be recalled; evidence states those limits.
System design derived from the flows
Revocation and audit fail when each service invents its own identifiers, clock, and retry semantics, because investigators cannot distinguish delay from data loss. The architecture uses each plane’s authoritative state plus a shared versioned event and lineage contract.
| Use case ID | Entry point | Responsible services | Authoritative store | Failure evidence |
|---|---|---|---|---|
| D11-UC-01 | Security console and grant-specific administration APIs | Provider membership/deployment/preview/connector services; generated-app share and session services; revocation orchestrator and transactional outbox; cache invalidator; runtime supervisor; stream closer; signed-URL service; job canceller; residual probe runner | The target grant remains authoritative in its owning provider, runtime, or app store; revocation workflow store owns convergence status; append-only evidence ledger owns observations | Event publication lag, stale version accepted, unacknowledged leg, deadline breach, surviving stream/job/token, first-denial latency, residual limitation, and unaffected-control regression |
| D11-UC-02 | Provider incident explorer and SIEM export API | Event collectors; trace propagator; lineage indexer; redaction service; metrics pipeline; completeness monitor; immutable evidence ledger; signed exporter | Append-only authorization event store owns redacted decisions; trace index owns joins; metrics time-series store owns aggregates; customer SIEM owns exported copy | Missing required edge/field, clock skew, duplicate or late event, redaction canary hit, export rejection, policy-digest mismatch, and replay outcome |
Every tool-decision event records timestamp, organization, active team, subject, agent and version, deployment, run, connector, protocol server, tool, constrained resource, decision and reason, approval identity, credential mode, provider-subject hash, policy bundle and digest, argument digest, result, and duration. It must not record raw prompts containing secrets, OAuth access or refresh tokens, API keys, session cookies, unredacted document bodies, or full sensitive tool results.
Stable lineage is hierarchical: session_id owns run_id; a run links model and retrieval requests plus tool intents; each intent links authorization decision, approval, MCP request, and downstream request; child-agent runs keep parent_run_id. Metrics include run and tool decisions by reason, cross-team invocation, credential-resolution mode, approval outcomes, authorization staleness, invalid audience, token-passthrough attempts, privilege-escalation denies, and prompt-injection tool denies. Metrics diagnose patterns; immutable events prove individual decisions.
Data model and ownership
Convergence cannot be proved if revocation events overwrite one another or if app sessions are stored in the provider membership table, so the model preserves independent authorities and append-only observations. Cross-plane target references are opaque and re-resolved by the owning service before any state change.
Generated-application database: Required in this slice — each generated application owns its share policy, audience grants, session index, subscriptions, signed-object references, and domain-job authorization versions so app access can be revoked independently of provider collaboration and runtime deployment.
| Record or entity | Store and owner | Primary key | Foreign key or opaque reference | Tenant key | Material constraint | Lifecycle and deletion | Use case IDs |
|---|---|---|---|---|---|---|---|
| RevocableAuthority | Owning provider grant store or generated-app policy store; relevant membership, deployment, connector, preview, approval, or app service | authority_type plus authority_id | Local subject/resource references within owner; opaque cross-plane mappings only | organization_id plus optional team_id or app_tenant_id | Status and monotonic version change atomically; one plane’s disable never implies another plane’s grant removal | Create on explicit grant; disable/revoke independently; tombstone through convergence and audit retention; then purge personal fields | D11-UC-01 |
| AppSharePolicy | Generated-app database; app policy service | app_share_policy_id | Opaque provider deployment reference | app_tenant_id or route-scoped public sentinel | Visibility, protected routes, mutation defaults, and policy version are mandatory; public create never implies read/admin/export | Versioned updates; archive with app; retain decision metadata; state that prior downloads remain outside recall | D11-UC-01, D11-UC-02 |
| AppAudienceGrant | Generated-app database; app audience service | app_audience_grant_id | Local FK app_share_policy_id and app principal/group reference | app_tenant_id | Audience, role, scope, expiry, and revocation version required; no provider/preview inheritance | Revoke independently; tombstone until sessions, streams, URLs, and jobs converge; purge after retention | D11-UC-01 |
| PreviewCapability | Preview delivery store; provider preview service | preview_capability_id | Opaque project, preview, revision, and optional provider-principal references | organization_id | Hash-only token; audience, methods, environment, revision, expiry, and revocation epoch required | Revoke or expire; purge edge cache, close preview streams, cancel queued preview work; retain residual statement for downloaded bytes | D11-UC-01, D11-UC-02 |
| CapabilityLink | Generated-app database; app capability service | capability_link_id | Local FK app_share_policy_id and route; token represented only by hash | app_tenant_id or route-scoped public sentinel | Audience, method, route, scope, expiry, and revocation epoch required; possession grants no administration | Revoke or expire; invalidate caches and streams; delete hash after retention while prior downloads remain outside recall | D11-UC-01 |
| SessionIndex | Generated-app session-control store; app identity service | session_index_id | Hashed session ID; local app_audience_grant_id; opaque provider subject | app_tenant_id | Cache key includes app, tenant, principal, policy, membership, visibility, and grant versions | Expire or destroy on revocation; close streams; retain minimal denial correlation; purge bearer/session material | D11-UC-01, D11-UC-02 |
| AppAuthorizedJob | Generated-app job store; app workflow service | app_job_id | Local app principal/grant references; opaque provider run and decision references | app_tenant_id | Captures initiating principal, tenant, policy/grant versions, operation, arguments digest, and cancellation state; must reauthorize before side effect | Cancel or terminally deny on stale version; preserve redacted attempt evidence; delete payload with app data retention | D11-UC-01, D11-UC-02 |
| RevocationJob | Security workflow store; revocation orchestrator | revocation_job_id | Opaque target type/ID plus source version; local parent event reference | organization_id plus optional app_tenant_id | Idempotency key, requested version, deadline, and per-leg retry state prevent stale reactivation | Append request and leg transitions; archive immutable completion evidence; delete transient payload after retention | D11-UC-01, D11-UC-02 |
| RevocationEvent | Durable event log; outbox and event-stream owner | event_id plus partition offset | Local FK revocation_job_id; opaque target and subject references | organization_id | At-least-once delivery with idempotent consumers; versions never decrease; occurred time and producer time both recorded | Publish transactionally with authority change; compact payload only after all acknowledgments and audit retention | D11-UC-01, D11-UC-02 |
| ConvergenceLeg | Revocation workflow store; probe runner | revocation_job_id plus leg_name | Local FK revocation_job_id; opaque cache/session/run/job/stream reference | organization_id plus optional app_tenant_id | Records target version, deadline, retries, first denial, unaffected control, and residual limitation | Update by monotonic state machine; freeze final evidence; remove operational payload after signed report export | D11-UC-01, D11-UC-02 |
| AuthorizationDecisionEvent | Append-only evidence ledger; security operations | decision_id | Opaque actor, app session, run, deployment, connector, policy, approval, and downstream references | organization_id plus active team_id and optional app_tenant_id | Required actor/resource/scope/precondition/expected/observed/environment/time fields; secrets redacted; immutable after append | Retain by audit policy; legal hold where required; export signed subset; delete/aggregate after retention | D11-UC-01, D11-UC-02 |
| TraceLineageEdge | Trace index; observability platform | parent_id plus child_id plus edge type | Opaque IDs into immutable producer events | organization_id | Required edge types form an acyclic run tree; late events preserve original event time and offset | Append and reconcile; alert on missing edge; rebuild from ledger; expire index after ledger retention | D11-UC-02 |
| AuditExportBatch | Export store; SIEM exporter | export_batch_id | Local event-range references; opaque customer SIEM acknowledgment | organization_id | Signed manifest, contiguous offsets or explicit gaps, redaction pass, and idempotent destination key | Quarantine on gaps/canary hit; retry safely; retain manifest and acknowledgment; delete exported payload on schedule | D11-UC-02 |
For each revocation report, the product names what must become denied, what must remain allowed, and the irrecoverable residual. Removing project membership denies provider source, agent, preview configuration, and release actions but leaves a separately granted app membership and preview link. Revoking a preview capability denies its bound revision, streams, assets, and queued preview work but leaves project/app memberships. Removing an app grant denies tenant routes, subscriptions, object URLs, and app jobs but leaves provider role and preview access. Changing visibility removes former audience routes but preserves named administration only where current app policy permits.