Outcome
Place one declared provider reference in an authorized consumer resource, preserving current access checks and the existing-placement/version limits.
POST /api/developer-console/placements
Action: app_topolo_developers.placements.create.
Before you start
Use the original authenticated active organization with Developers connections:write and legitimate consumer-workspace read_write access. The worked caller is a person session; other principals follow the current credential-scoped policy. Review the actual consumer/reference placement and possible provider read before confirmation; no automatic connection enable, link approval or grant expansion is authorized.
Discover the real consumer app/workspace/kind/id and provider reference through supported resource reads. The consumer must declare consuming this provider type in the supplied consumerKind, and the provider must declare that reference type. The original connection must be unremoved and stored active or degraded. These stored states are not independent entitlement, provider-health or delivery proof.
For workspace-scoped references, the caller must currently use the provider workspace and the pair must satisfy the connection’s all/linked policy. Organization-wide reference workspace must equal the active organization id. These are the reference’s scoped identifiers, not an organization override or authority to create a workspace.
Every example below is a complete source-derived synthetic UNRUN action carrier. Hypothetical provider callbacks are premises, not real provider API captures. No placement, provider/private/grant/Notify/business operation, source edit or app import/test was performed. Current descriptor matches immutable7b89, not served-runtime certification.
Request
Discover actual resources first. All identifiers here are fictional:
{
"consumerAppId": "app_example_consumer",
"consumerWorkspaceId": "ws_consumer_example",
"consumerKind": "example.page",
"consumerId": "page_example",
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9"
}
Creation and existing-placement behavior
POST /api/developer-console/placements accepts consumerAppId,consumerWorkspaceId,consumerKind,consumerId,reference and optional slot. reference may be the supported topolo: string or strict object {app,workspace,type,id,version?}; native schema supplies exact identifier patterns and positive safe-integer version bounds. slot is an optional nonempty string up to80 characters; omit it for no slot rather than sending null or empty text. Do not infer the full reference grammar from the string’s broad schema prefix alone; the handler also parses it.
The service parses the reference, requires a live original-org connection with stored active/degraded status, checks current stored consumer/provider reference declarations, and requires consumer read_write access. Missing connection404, unusable status409 and undeclared consumer placement422 are refusals, not instructions to create a new connection or broaden permissions. This helper does not load the consumer object itself; correct consumerKind/id must be discovered by the caller rather than guessed.
Workspace-scoped references check current provider workspace access and the connection workspace policy/link. An organization-wide type instead requires reference.workspace to equal actor.organizationId. The service does not replace these checks with a catalog suggestion, stored label or old approval; no arbitrary provider get name, URL or organization id is admitted in input.
Before reading the provider resource, it searches for an existing unremoved placement using original organization, consumer app/workspace/kind/id, slot (SQL treats null/empty equivalently), and provider reference app/workspace/type/id. The lookup does NOT include reference.version. Therefore a request for the same identity with a different pin can return200 unchanged and the existing pin; it is not a version-update command. Current connection/declaration/workspace checks occur before this lookup, but unchanged skips the provider get and is not proof of current item visibility, freshness or matching pin.
With no existing live row, the selected caller port reads the provider’s declared get action with {id:reference.id}, using original caller credentials and provider workspace binding where applicable. It fetches current data, not the stored historical pin. A well-formed normalized current version different from a requested pin yields changed; otherwise the local best-effort check can yield ready. The same malformed normalization/version and resource-identity/business-state limits documented by placements.refresh apply; ready is not an integrity or publication certificate.
Provider check outcomes removed/access_removed/unavailable refuse insertion with404 reference_not_found,403 reference_access_denied or502 provider_unavailable respectively, each with details.reference holding the formatted requested reference. The selected failure occurs before placement insertion; shared request context may still initialize outside the helper. Auth workspace unavailable uses503; unexpected store/dependency failures are not fabricated as an empty success.
For a new acceptable check the store generates a placement id, saves original organization/consumer/slot/reference and optional pin, label/status/reason, creator, createdAt/updatedAt/lastCheckedAt, then reloads it. It does not mutate the consumer object, provider resource, grants, links, connection or subscriptions and sends no Notify event from this path.
The complete normal envelope is {success:true,message:"OK",data:{outcome:"created"|"unchanged",placement:<full stored PlacementRecord>}}. created usesHTTP201; unchanged uses200. A new record includes all15 mapped placement fields, with null slot/removal fields and optional reference.version only when stored. Duplicate lookup and insertion/reload are separate, with no expectedRevision or full-operation transaction; concurrent calls can race or fail. A final missing reload may serialize placement:null despite its TypeScript assertion. Never manufacture a second id or parallel replay after an uncertain result.
Worked responses
Create a declared consumer placement
Complete synthetic UNRUN HTTP201. Consumer declares example.item from this provider in example.page; provider type is workspace-scoped, connection is active/all, current caller consumer write/provider access pass, and no matching live placement exists. Hypothetical get callback returns a well-formed matching id/name Fixture item/version9. Fictional generated id/time are fixed by the fixture.
Request:
{
"consumerAppId": "app_example_consumer",
"consumerWorkspaceId": "ws_consumer_example",
"consumerKind": "example.page",
"consumerId": "page_example",
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9"
}
Response:
{
"success": true,
"message": "OK",
"data": {
"outcome": "created",
"placement": {
"id": "plc_docs-example-created",
"organizationId": "org_docs_fixture",
"consumer": {
"appId": "app_example_consumer",
"workspaceId": "ws_consumer_example",
"kind": "example.page",
"id": "page_example"
},
"slot": null,
"reference": {
"app": "app_example_provider",
"workspace": "ws_provider_example",
"type": "example.item",
"id": "item_example",
"version": 9
},
"referenceString": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9",
"label": "Fixture item",
"status": "ready",
"statusReason": null,
"lastCheckedAt": "2026-10-22T18:00:00.000Z",
"createdBy": "user_docs_fixture",
"createdAt": "2026-10-22T18:00:00.000Z",
"updatedAt": "2026-10-22T18:00:00.000Z",
"removedBy": null,
"removedAt": null
}
}
}
Verify the returned original-org identity and pin. No actual consumer/provider record, connection or grant was changed.
A different requested pin does not update an existing placement
Complete synthetic UNRUN HTTP200 with the preceding live row already present. Prerequisite declaration/workspace checks pass, but the dedup lookup excludes version, so no provider get runs and saved version9 is returned despite requested10.
Request:
{
"consumerAppId": "app_example_consumer",
"consumerWorkspaceId": "ws_consumer_example",
"consumerKind": "example.page",
"consumerId": "page_example",
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@10"
}
Response:
{
"success": true,
"message": "OK",
"data": {
"outcome": "unchanged",
"placement": {
"id": "plc_docs-example-created",
"organizationId": "org_docs_fixture",
"consumer": {
"appId": "app_example_consumer",
"workspaceId": "ws_consumer_example",
"kind": "example.page",
"id": "page_example"
},
"slot": null,
"reference": {
"app": "app_example_provider",
"workspace": "ws_provider_example",
"type": "example.item",
"id": "item_example",
"version": 9
},
"referenceString": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9",
"label": "Fixture item",
"status": "ready",
"statusReason": null,
"lastCheckedAt": "2026-10-22T18:00:00.000Z",
"createdBy": "user_docs_fixture",
"createdAt": "2026-10-22T18:00:00.000Z",
"updatedAt": "2026-10-22T18:00:00.000Z",
"removedBy": null,
"removedAt": null
}
}
}
Do not claim the pin became10 or the item was freshly checked. Preserve the actual row and propose any pin migration as a separate reviewed workflow.
The provider resource read is denied
Complete synthetic UNRUN HTTP403 for a new identity whose prerequisite checks pass but hypothetical provider get produces an access-denied check before insertion.
Request:
{
"consumerAppId": "app_example_consumer",
"consumerWorkspaceId": "ws_consumer_example",
"consumerKind": "example.page",
"consumerId": "page_example",
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9"
}
Response:
{
"success": false,
"error": {
"message": "You cannot read this resource in the provider",
"code": "reference_access_denied",
"details": {
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9"
}
}
}
No local placement was inserted by this branch. Do not create broader grants or bypass current provider policy.
The provider could not be reached for a new placement
Complete synthetic UNRUN HTTP502 from the handled unavailable check before insertion, not an assertion of zero shared-context effects.
Request:
{
"consumerAppId": "app_example_consumer",
"consumerWorkspaceId": "ws_consumer_example",
"consumerKind": "example.page",
"consumerId": "page_example",
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9"
}
Response:
{
"success": false,
"error": {
"message": "The provider could not be reached; nothing was placed",
"code": "provider_unavailable",
"details": {
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9"
}
}
}
Preserve real dependency and request evidence; reconcile original consumer-visible placement state before any later approved attempt.
The consumer workspace permits reads only
Complete synthetic UNRUN HTTP403 from requireWorkspace(read_write) after the stored connection/reference-declaration checks. This helper includes details unlike delete/get’s visibility helper.
Request:
{
"consumerAppId": "app_example_consumer",
"consumerWorkspaceId": "ws_consumer_example",
"consumerKind": "example.page",
"consumerId": "page_example",
"reference": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9"
}
Response:
{
"success": false,
"error": {
"message": "You can only read workspace ws_consumer_example of app_example_consumer",
"code": "workspace_write_required",
"details": {
"appId": "app_example_consumer",
"workspaceId": "ws_consumer_example"
}
}
}
Use the legitimate consumer-workspace owner workflow. Do not broaden access automatically or mistake provider access for consumer write authority.
Verify and recover
-
Compare actual outcome, full placement.id/organizationId/consumer/slot/reference/referenceString and stored pin to the approved intent. In particular unchanged may return a different pin from the request because lookup ignores version; do not silently accept that as a version update.
-
Use placements.get/list in the original authorized consumer context to reconcile the exact returned id. Status/label/check time are saved snapshots, not continuing provider rights or runtime delivery. Retain the actual request id and outcome before any further mutation.
-
After refusal/timeout, reconcile whether a placement already exists before retrying. No automatic new connection, grant/link approval, duplicate id, deletion or provider write. Resolve the actual declaration/access/dependency issue through its owner.
-
A separately approved deletion removes the local placement only and is not an inverse of a provider read or consumer-object history. Changing an existing pin is not performed by create’s unchanged branch; do not delete/recreate merely to force it without a reviewed plan.
Read actual returned/discovered placement state first. A separately approved placements.delete soft-removes the local row only; it does not undo provider reads, consumer-object history or restore a requested version pin. Never parallel-retry, invent ids or delete/recreate to force a pin change after unknown effects.
Related actions
- Read a placement to reconcile its saved identity and pin.
- Delete a local placement only as a separately approved cleanup.
Change log
- 2026-10-22: Added exact declaration/access prerequisites, full201/200/refusal carriers, dedup lookup excluding version, provider-read versus stored snapshot limits and safe compensation. All examples synthetic UNRUN; no real placement/provider operation performed.