[Design Discussion] Resource representation of Entity #5128
Replies: 8 comments
Update: Team Discussion OutcomesFollowing an internal team discussion, several decisions were made that affect the scope and design of this feature. Decisions1:1 cardinality confirmed. One entity will always own at most one RS. The 1:N case (R3, previously parked) is not needed. Cross-entity access confirmed. Other entities should be able to access an entity-owned RS and obtain tokens for it (R8). Scope split: dedicated entities vs templated entities. The team agreed that resource representation should ultimately live at the Type level (per #5193, Entity Type/Template model). When the Type/Template system lands, templated entities will inherit their RS binding from their Type definition rather than requiring per-entity binding. This splits the work into two tracks:
These are not competing approaches. They serve different entity categories. A dedicated agent owns its RS directly (Part 1). A templated agent inherits RS from its Type (Part 2). What this means for the current designThe design in this discussion (#5128) covers Part 1 only: entity-level RS ownership for dedicated agents and apps. The data model, API surface, audience resolution, and lifecycle handling all apply to dedicated entities. Part 2 (#5196) will extend or adapt this design for the Type-level binding when #5193 is ready. |
Use Cases1. Multi-agent invocationAn enterprise deploys multiple AI agents: a "Customer Data" agent, a "Fraud Detection" agent, and an orchestrator that coordinates them. The orchestrator needs to call the other agents' MCP tools to complete a workflow. Each target agent exposes resources that must be protected by the identity platform. Without entity-RS binding, the identity platform has no knowledge that these agents serve resources. The orchestrator must somehow know each agent's RS identifier out of band, and there is no identity-level boundary controlling which agents can call which. Any client in the deployment that knows the RS identifier can request a token for it. With entity-RS binding, each agent's resources are a first-class object in the identity platform. The orchestrator resolves the target agent to its resources through the platform, and the platform can enforce who is authorized to invoke each agent. This extends to delegation chains (Agent A delegates to Agent B, which sub-delegates to Agent C) where each hop requires a token for the next agent's resources. It also covers human users invoking agents through client applications, where the app needs a token for the agent's RS. 2. Exposing an agent's resourcesA team deploys a "Document Extraction" agent. Other agents and applications across the organization need to call this agent to extract text and parse invoices. The agent exposes these capabilities through an MCP endpoint that callers connect to remotely. To invoke the agent's tools, callers need an OAuth token scoped to the agent's resources. Today, making this work requires manual setup: create a standalone resource server, set its identifier to match the MCP server's PRM, and mentally track that this RS "belongs to" the agent. There is no guided path from "I have an agent" to "others can securely invoke it." With entity-RS binding, the developer binds an RS to the agent. The agent's resources are now part of the identity platform, discoverable and protectable. This scales naturally to the shared service model: a team builds a "Code Review" agent and publishes it for other teams to consume by binding an RS and defining the scopes for the tools it exposes. 3. Agent self-registration (future)An AI agent starts up in a containerized environment, discovers it is running an MCP server, and needs to register its resources with the identity platform dynamically. Today, agents can register their client identity through Dynamic Client Registration (DCR). But there is no equivalent for the resource side. The agent can say "I exist" but not "I serve these resources." Entity-RS binding lays the groundwork for resource-side self-registration: an agent registers itself as a resource provider at startup. This is deferred from v1 (which uses admin-configured binding), but the entity-RS ownership model is the foundation it builds on. 4. MCP server and agent identity as oneAn agent runs an MCP server protected by OAuth. In the MCP authorization flow, a client discovers the agent's Protected Resource Metadata (PRM), which declares the RS identifier and the authorization server. The client requests a token from the authorization server with that RS as audience, then calls the agent with the token. Today, the MCP server's RS identity and the agent's client identity are separate, unrelated objects in the platform. The PRM declares an RS identifier, but nothing in the identity platform ties that RS to the agent. If the agent's credentials are rotated, the RS does not know. If the agent is removed, the RS lingers. With entity-RS binding, the agent and its MCP server are one identity in the platform. The RS bound to the agent is the same RS declared in the PRM. Token issuance, credential management, and lifecycle are all unified. The complete MCP authorization flow (PRM discovery, token request, token validation) stays consistent because both sides point to the same identity. 5. Agent-side token validationWhen an agent receives an incoming request with an OAuth token, it must validate that the token was issued for its resources by checking the Without entity-RS binding, the agent's RS identifier is a configuration value managed separately from its identity in the platform. In containerized or auto-scaled deployments, this creates a bootstrapping problem: the agent needs to be configured with a value that lives in a separate system, and that value can drift from what the platform actually has. With entity-RS binding, the agent can query the identity platform for its own resource identity. "I am Agent B. What is my RS identifier?" The platform answers from the binding, and the agent uses that value for token validation. The agent's resource identity is always in sync with the platform. 6. Audit and access analyticsAn admin needs to answer: "Which entities are accessing the financial data agent's resources, and how often?" Without entity-RS binding, the agent and its RS are separate objects. Answering this question requires manually correlating RS access logs with agent identities. Token request metrics are tracked per RS, with no link to the agent that owns those resources. With entity-RS binding, the platform natively connects agent identity to resource access. An admin can see per-agent analytics: which agents are the most accessed resource providers, how many token requests target each agent, and which callers are invoking which agents. Compliance audits become straightforward because the platform can answer "who can access this agent?" directly. 7. Agent decommissioningAn enterprise retires an agent. The agent's identity is deleted from the platform. But the resource server that represented the agent's tools remains as a standalone object. The platform does not know the RS belonged to the deleted agent, so it continues to issue tokens with that audience. Orphaned resource configurations are a security risk: tokens are being issued for resources that no longer exist. With entity-RS binding, deleting the agent cascade-deletes its owned RS. No orphaned configurations, no stale tokens. The admin receives a warning showing the full impact before confirming deletion. |
Backend Design: Entity Resource Server OwnershipFeature design for binding agents and applications to the resource servers they expose, enabling lifecycle governance, discovery, and coherent identity across the client and resource sides. 1. Design Decisions
2. Database SchemaThe binding lives on the New Columns on RESOURCE_SERVER
Constraints-- Both owner fields must be set together or both null
ALTER TABLE "RESOURCE_SERVER" ADD CONSTRAINT chk_owner_fields_complete
CHECK (
("OWNER_ENTITY_ID" IS NULL AND "OWNER_ENTITY_TYPE" IS NULL)
OR ("OWNER_ENTITY_ID" IS NOT NULL AND "OWNER_ENTITY_TYPE" IS NOT NULL)
);
-- Owner type must be a valid entity category
ALTER TABLE "RESOURCE_SERVER" ADD CONSTRAINT chk_owner_entity_type
CHECK ("OWNER_ENTITY_TYPE" IS NULL
OR "OWNER_ENTITY_TYPE" IN ('agent', 'application'));
-- One RS per entity (partial unique index, Postgres)
CREATE UNIQUE INDEX uq_rs_owner_entity
ON "RESOURCE_SERVER" ("OWNER_ENTITY_ID", "DEPLOYMENT_ID")
WHERE "OWNER_ENTITY_ID" IS NOT NULL;
-- Reverse lookup: find RS by owner
CREATE INDEX idx_rs_owner_lookup
ON "RESOURCE_SERVER" ("DEPLOYMENT_ID", "OWNER_ENTITY_ID")
WHERE "OWNER_ENTITY_ID" IS NOT NULL;
Migration Script-- Postgres migration
ALTER TABLE "RESOURCE_SERVER"
ADD COLUMN "OWNER_ENTITY_ID" VARCHAR(36),
ADD COLUMN "OWNER_ENTITY_TYPE" VARCHAR(50);
-- Add constraints (as above)
-- Backfill: all existing RS get NULL owner (standalone)3. API Contract: New EndpointsThree new sub-resource endpoints on both GET /agents/{agentId}/resource-serverReturns the resource server owned by this agent. Response 200: {
"id": "8f3a1b2c-...",
"name": "Document Extraction API",
"identifier": "https://extraction.example.com",
"type": "MCP",
"ouId": "ou-uuid",
"delimiter": ":"
}Status codes: POST /agents/{agentId}/resource-serverBind an existing resource server or create a new one and bind it. Discriminated by whether Mode A: Bind Existing {
"resourceServerId": "existing-rs-uuid"
}Mode B: Create and Bind {
"name": "Document Extraction API",
"identifier": "https://extraction.example.com",
"type": "MCP",
"ouId": "ou-uuid",
"delimiter": ":"
}When Response 201: {
"id": "8f3a1b2c-...",
"name": "Document Extraction API",
"identifier": "https://extraction.example.com",
"type": "MCP",
"ouId": "ou-uuid",
"delimiter": ":",
"ownerId": "agent-uuid",
"ownerType": "agent"
}Status codes: DELETE /agents/{agentId}/resource-serverUnbind the resource server from this agent. The RS is not deleted, it becomes a standalone resource server. Status codes:
4. Modified Existing ResponsesResource Server Responses
Agent / Application Responses
Query Filters5. Core Backend ChangesResource Server Domain
Agent Domain
Application Domain
Entity Service (Shared)
Declarative Resources
6. Cross-DB Fan-Out PatternAgents and applications live in entitydb. Resource servers live in configdb. No cross-DB JOINs. The binding column ( graph LR
subgraph entitydb
E["ENTITY<br/>(agents, apps)"]
end
subgraph configdb
RS["RESOURCE_SERVER<br/>+ OWNER_ENTITY_ID<br/>+ OWNER_ENTITY_TYPE"]
end
E -. "service-layer<br/>fan-out" .-> RS
RS -. "resolve<br/>ownerName" .-> E
Read Paths
7. Frontend ChangesAgent Edit Page
Application Edit Page
Resource Server Edit Page
Resource Server List Page
Agent/Application Create Wizard
New API Hooks
8. Sequence FlowsBind Existing Resource ServersequenceDiagram
participant UI as Console UI
participant AH as Agent Handler
participant AS as Agent Service
participant RS as RS Service
participant CDB as configdb
participant EDB as entitydb
UI->>AH: POST /agents/{id}/resource-server<br/>{ resourceServerId: "rs-1" }
AH->>AS: BindResourceServer(agentId, rsId)
AS->>EDB: GetEntity(agentId) — verify exists
EDB-->>AS: Agent found
AS->>RS: GetByOwnerEntityID(agentId)
RS->>CDB: SELECT WHERE owner_entity_id = agentId
CDB-->>RS: No rows
RS-->>AS: No existing binding ✓
AS->>RS: GetResourceServer(rsId)
RS->>CDB: SELECT WHERE id = rsId
CDB-->>RS: RS found, owner = NULL
RS-->>AS: RS is unowned ✓
AS->>RS: BindOwner(rsId, agentId, "agent")
RS->>CDB: UPDATE SET owner_entity_id, owner_entity_type
CDB-->>RS: Done
RS-->>AS: Bound RS
AS-->>AH: 201 Created
AH-->>UI: RS response with owner fields
Block Agent DeletionsequenceDiagram
participant UI as Console UI
participant AH as Agent Handler
participant AS as Agent Service
participant DEP as Dependency Registry
participant RS as RS Service
participant CDB as configdb
UI->>AH: DELETE /agents/{id}
AH->>AS: DeleteAgent(agentId)
AS->>DEP: GetDependencies(agent, agentId)
DEP->>RS: GetByOwnerEntityID(agentId)
RS->>CDB: SELECT WHERE owner_entity_id = agentId
CDB-->>RS: RS "extraction-api" found
RS-->>DEP: BehaviorRestrict: RS "extraction-api"
DEP-->>AS: Blocking dependency exists
AS-->>AH: 409 Conflict
AH-->>UI: "Cannot delete: agent owns<br/>resource server 'extraction-api'.<br/>Unbind or delete the RS first."
Auto-Create on Agent Creation (Post-Create Step)sequenceDiagram
participant UI as Console UI
participant AH as Agent Handler
participant AS as Agent Service
participant RS as RS Service
participant CDB as configdb
Note over UI: Agent already created in previous step
UI->>AH: POST /agents/{id}/resource-server<br/>{ name, identifier, type }
AH->>AS: CreateAndBindResourceServer(agentId, rsPayload)
AS->>RS: CreateResourceServer(rsPayload)
RS->>CDB: INSERT INTO RESOURCE_SERVER
CDB-->>RS: RS created (id = "new-rs")
RS-->>AS: New RS
AS->>RS: BindOwner("new-rs", agentId, "agent")
RS->>CDB: UPDATE SET owner fields
CDB-->>RS: Done
RS-->>AS: Bound RS
AS-->>AH: 201 Created
AH-->>UI: RS response
Refs #2456 |
UI Design: Entity Resource Server OwnershipMockups match the existing ThunderID Console design system (Oxygen UI, Screen 1: Agent Edit Page, Resource Server Tab (Bound State)New "Resource Server" tab on the agent detail page. When bound, shows a card with:
Screen 2: Agent Edit Page, Resource Server Tab (Unbound State)Same tab, empty state:
Screen 3: Resource Server Edit Page, Owner BadgeRS detail page header gains an owner chip next to the type badge:
Screen 4: Resource Server List Page, Owner ColumnData grid gains an Owner column between Identifier and Actions:
Screen 5: Agent Create Wizard, Resource Server StepOptional final wizard step after Owner:
Application Edit PageSame "Resource Server" tab pattern as the agent edit page (not separately mocked since the layout is identical). New Frontend Hooks
Refs #2456 |
Design Revisions 02Three updates to the backend design based on further review. 1. Drop "Create and Bind" from the bind endpointThe current design has Revised flow: RS creation and binding are always two separate operations.
The bind endpoint only accepts a resource server ID. No RS creation fields. 2. Flip the ownership direction: entity has a resourceThe current design puts Revised direction: Put The previous design placed the reference on the RS table (configdb) pointing to entitydb. This meant configdb was referencing entitydb, when the natural dependency direction is the other way around: entitydb should reference configdb. Flipping the column to the entity side corrects this. Why this is better:
What changes:
Schema change: ALTER TABLE "ENTITY"
ADD COLUMN "RESOURCE_SERVER_ID" VARCHAR(36);
-- Users cannot have a resource server
ALTER TABLE "ENTITY" ADD CONSTRAINT chk_user_no_rs
CHECK ("CATEGORY" != 'user' OR "RESOURCE_SERVER_ID" IS NULL);
CREATE INDEX idx_entity_rs_lookup
ON "ENTITY" ("RESOURCE_SERVER_ID")
WHERE "RESOURCE_SERVER_ID" IS NOT NULL;No constraints on the RS side. No The ENTITY table is unified with a CATEGORY discriminator (user/app/agent). The CHECK constraint enforces at the database level that only agents and applications can have a bound RS. Users are always null. 3. Audience resolution from entity ownershipDecision. A bound resource server becomes the entity's default audience. When that entity requests a token without a Where it inserts.
Path 3 is today's behavior untouched, so entities without a binding need no migration. The single-resource-server invariant holds. An entity carries at most one Binding changes the token shape. After an RS is bound, that entity's newly issued tokens move Dangling references after RS deletion. Proposal: clean up on delete as the primary path, so deleting an RS nulls the column on every entity referencing it. At resolution time, treat a dangling reference as a fall-through to path 3 plus a warning log, so a missed cleanup degrades instead of breaking token issuance. Revised API ContractThree sub-resource endpoints on both GET /agents/{agentId}/resource-serverReturns the resource server bound to this agent. Request: Response 200: {
"id": "8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Document Extraction API",
"identifier": "https://extraction.example.com",
"type": "MCP",
"ouId": "ou-uuid",
"delimiter": ":"
}Status codes: POST /agents/{agentId}/resource-serverBind an existing resource server to this agent. The RS must be created separately via Request: Response 201: {
"id": "8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Document Extraction API",
"identifier": "https://extraction.example.com",
"type": "MCP",
"ouId": "ou-uuid",
"delimiter": ":"
}Status codes: DELETE /agents/{agentId}/resource-serverUnbind the resource server from this agent. Sets Request: Response: Status codes:
Modified Existing ResponsesAgent / Application responses gain two optional fields:
Resource Server responses are unchanged. The RS does not carry owner information. To find which entities reference an RS, query entitydb. Query FiltersRevised Sequence DiagramsBind Resource Server to AgentsequenceDiagram
participant UI as Console UI
participant AH as Agent Handler
participant AS as Agent Service
participant RS as RS Service
participant EDB as entitydb
participant CDB as configdb
UI->>AH: POST /agents/{id}/resource-server<br/>{ resourceServerId: "rs-1" }
AH->>AS: BindResourceServer(agentId, rsId)
AS->>EDB: GetEntity(agentId)
EDB-->>AS: Agent found, RESOURCE_SERVER_ID = NULL
Note over AS: Agent has no existing binding
AS->>RS: GetResourceServer(rsId)
RS->>CDB: SELECT WHERE id = rsId
CDB-->>RS: RS found
RS-->>AS: RS exists
AS->>EDB: UPDATE ENTITY SET RESOURCE_SERVER_ID = rsId<br/>WHERE ID = agentId
EDB-->>AS: Updated
AS-->>AH: 201 Created
AH-->>UI: RS response
Unbind Resource Server from AgentsequenceDiagram
participant UI as Console UI
participant AH as Agent Handler
participant AS as Agent Service
participant EDB as entitydb
UI->>AH: DELETE /agents/{id}/resource-server
AH->>AS: UnbindResourceServer(agentId)
AS->>EDB: GetEntity(agentId)
EDB-->>AS: Agent found, RESOURCE_SERVER_ID = "rs-1"
AS->>EDB: UPDATE ENTITY SET RESOURCE_SERVER_ID = NULL<br/>WHERE ID = agentId
EDB-->>AS: Updated
AS-->>AH: 204 No Content
AH-->>UI: Success
Get Agent's Resource Server (Fan-out)sequenceDiagram
participant UI as Console UI
participant AH as Agent Handler
participant AS as Agent Service
participant RS as RS Service
participant EDB as entitydb
participant CDB as configdb
UI->>AH: GET /agents/{id}/resource-server
AH->>AS: GetResourceServer(agentId)
AS->>EDB: GetEntity(agentId)
EDB-->>AS: Agent found, RESOURCE_SERVER_ID = "rs-1"
AS->>RS: GetResourceServer("rs-1")
RS->>CDB: SELECT WHERE id = "rs-1"
CDB-->>RS: RS details
RS-->>AS: RS response
AS-->>AH: 200 OK
AH-->>UI: RS response
Agent Deletion (No Blocking)sequenceDiagram
participant UI as Console UI
participant AH as Agent Handler
participant AS as Agent Service
participant EDB as entitydb
UI->>AH: DELETE /agents/{id}
AH->>AS: DeleteAgent(agentId)
AS->>EDB: GetEntity(agentId)
EDB-->>AS: Agent found, RESOURCE_SERVER_ID = "rs-1"
Note over AS: RS reference is on entity row.<br/>Deleting the entity removes the reference.<br/>RS "rs-1" is unaffected.
AS->>EDB: DELETE FROM ENTITY WHERE ID = agentId
EDB-->>AS: Deleted
AS-->>AH: 204 No Content
AH-->>UI: Success
Audience Resolution at Token IssuancesequenceDiagram
participant C as Client (Agent A)
participant TH as Token Handler
participant RAB as ResolveAudienceBinding
participant EDB as entitydb
participant CDB as configdb
C->>TH: POST /token (client_credentials, no resource param)
TH->>RAB: ResolveAudienceBinding(request)
Note over RAB: No resource parameter supplied
RAB->>EDB: GetEntity(clientEntityID)
EDB-->>RAB: RESOURCE_SERVER_ID = "rs-1"
RAB->>CDB: GetResourceServer("rs-1")
alt RS found
CDB-->>RAB: identifier = https://extraction.example.com
Note over RAB: aud = RS identifier<br/>token is RS-bound<br/>scopes downscoped to RS permissions
RAB-->>TH: Bound to rs-1
else RS missing (dangling reference)
CDB-->>RAB: not found
Note over RAB: Fall through to path 3<br/>aud = default audience / client ID<br/>log warning
RAB-->>TH: Unbound
end
TH-->>C: access_token
|
Revised UI Design: Entity Resource Server OwnershipUpdated mockups to match the revised backend design. Key changes: no owner information on RS pages, N:1 support (multiple entities can share one RS), and a unified bind flow with a mode toggle between "Select Existing" and "Create New." The "Create New" mode is a UX convenience. Under the hood it makes two API calls: Mockups follow the existing ThunderID Console design system (Oxygen UI, Screen 1: Agent Edit Page, Resource Server Tab (Bound State)When the agent has a bound RS, the tab shows a card with the RS name, identifier (monospace), and type badge (MCP/API/Custom). A details grid displays identifier, type, delimiter, and organization. Two actions: View Resource Server (outlined, links to RS detail page) and Unbind (danger-outlined, detaches without deleting the RS).
Screen 2: Agent Edit Page, Resource Server Tab (Unbound State)When no RS is bound, the tab shows an empty state with a dashed-border icon placeholder and "No resource server bound" heading. Two actions: Create New Resource Server (primary, opens the bind flow in "Create New" mode) and Bind Existing (outlined, opens the bind flow in "Select Existing" mode).
Screen 3a: Bind Resource Server (Select Existing)A mode toggle at the top switches between Select Existing and Create New. The "Select Existing" mode shows a searchable list of available resource servers. Each item shows the RS name, type badge, and identifier with radio selection. A callout notes: "Multiple agents can share the same resource server." Footer has Cancel and Bind Resource Server (primary) buttons.
Screen 3b: Bind Resource Server (Create New)Same page, toggled to "Create New" mode. Shows an inline form with three fields: Name (text input), Identifier (monospace input with hint: "The audience URI used in token requests"), and Type (dropdown: API/MCP/Custom). Footer has Cancel and Create & Bind (primary) buttons. Under the hood, submitting calls
Screen 4: Resource Server List PageThe RS list page is unchanged from the current design. No owner column, since the RS does not carry ownership information in the revised model. The relationship lives on the entity side. To find which entities reference an RS, admins check the agent or application pages (or use the query filter
Screen 5: Agent Create Wizard, Resource Server StepOptional final wizard step (step 4, after General, Credentials, Owner). Heading: "Resource Server" with subtext: "Create a new resource server or select an existing one to bind to this agent. You can also skip and do this later." Same mode toggle as the bind flow: Create New (default, shows inline form with Name, Identifier, Type) and Select Existing (shows RS picker with search). Footer: Back, Skip (outlined, creates agent without RS), and Create Agent (primary).
Application PagesSame "Resource Server" tab pattern as the agent pages. Not separately mocked since the layout is identical. Changes from Previous UI Design
Frontend Hooks
Refs #2456 |
Revision 2: Entity Inbound AccessCovers agents and applications. Requirements and acceptance criteria are in #2456. 1. The model
An entity's resource server is its inbound access: the audience callers target and the permissions they may request. The console gets one new Inbound Access tab; existing tabs are untouched, and the resource server stays visible only as plumbing. Naming trap for implementers. The codebase calls the entity's OAuth client the 2. Decisions
3. Data model
4. APISub-resource endpoints on
Permissions are edited through the existing resource server permission endpoints, and the console reuses the resource server permission editor pointed at the owned resource server. No new permission endpoints. Entity read responses carry
5. Token issuanceNo change in any grant. A resource server bound to an entity is the audience that other applications target when they call that entity, by passing Reaching an agent is done by a separate application holding its own client. That application asks for a token naming the agent as the resource, then calls the agent with it. An agent's own client obtains only tokens the agent spends outward:
An audience names the resource server, not the entity. Where several entities share one, a token minted to call one is equally valid at the others, which is the point: they are the same service behind one endpoint. An entity that needs a boundary of its own needs its own identifier. No grant handler reads 6. ConsoleCovered in the Revision 2: Console comment below. Scope there is the new Inbound Access tab only; existing tabs keep their names, order and content. 7. Open concerns
8. Out of scope
|


















Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Design discussion for #2456 (Introduce resource representation for entities).
Context
An application or agent that exposes resources has no identity those resources can be reached through. Resource servers exist in isolation, with no link to the entity that serves them, so a caller has nothing to target and an admin has nothing to manage. This discussion covers giving an entity its own resource server, which is its inbound access.
An entity's resource server is the audience other applications and agents target when they call that entity, and the permission set their tokens are scoped to. Entities that are the same service behind one endpoint share one. It plays no part in the tokens the entity itself obtains, which are for calling other services.
Requirements (from #2456)
The following requirements are in scope for this design. Full details and acceptance criteria are in the requirements comment.
In Scope
Covered Elsewhere
Mirrors the table in #2456 so the two cannot drift.
Design Decisions
RESOURCE_SERVER_IDon the ENTITY table (entitydb), not owner columns on the RS table (configdb). Corrects the DB dependency directionagentandapplicationresourceto call this entity. It is never the default audience for the entity's own tokensDesign Areas
Full detail, including schema, API contract and the per grant audience table, is in the Revision 2 design comment.
1. Data Model
RESOURCE_SERVER_IDcolumn on theENTITYtable in entitydb. Nullable, and not unique, since several entities may reference one resource server. A CHECK constraint ensures users cannot have a value. The RS table in configdb gains two type values. Cross-DB reference validated at the service layer.2. API Surface
Sub-resource endpoints on
/agents/{id}/resource-serverand/applications/{id}/resource-server:Agent and application responses gain
resourceServerIdand the inbound access identifier. RS responses are unchanged apart from the new type values.3. Audience
A resource server bound to an entity is the audience other applications target when they call that entity, by passing
resource=<identifier>.An entity is never among its own callers. Its own tokens, whether it acts as itself or on behalf of a user, are for calling other services, and they resolve their audience exactly as they do today. Token issuance is unchanged in every grant.
An audience names the resource server, not the entity. Where several entities share one, a token minted to call one is equally valid at the others.
4. Entity Deletion Handling
Deleting an entity drops its reference to the resource server. When no other entity references it, the resource server is deleted too, along with its permissions, cascading into roles that granted them the same way resource server deletion does today. The admin is warned first.
5. Console UX
An Inbound Access tab on the agent and application pages, with an enable dialog, the identifier and permission editor, and a destructive disable action. Existing tabs keep their names, order and content.
See: Revision 2: Console comment for the screens.
Scope Split
All reactions