Create a P2P capability
Declare one capability on an application you can edit. Retained source saves the declaration first and can immediately synchronize an eligible capability to P2P.
Source-reference guide. Behavior was reviewed at retained revision
7b89bd3b39092cdc29f87540847bf99a243f0a40and the pinnedc6e543source objects; separately recorded production descriptor reads matched the guide schemas. Public developer/publisher audience. No request below was executed. Serving runtime and P2P general availability are not established.
Before you start
PUBLIC developer/publisher audience with selected-app write access; public documentation does not grant action access. Pinned source-owner review is recorded; serving runtime currentness remains UNKNOWN.
The published credential requirement is app_topolo_developers.apps:write, authorizationMode static, readOnly false, destructive false, requiresConfirmation true, agentAccess confirm. The app access check is additional runtime policy.
The retained routes may call workspace-context helpers. Their complete identity and persistence effects are not qualified by this limited packet. Do not assert read-only prerequisite resolution.
All examples are fictional and UNRUN. Discover the real app and capability from current published reads and reconcile original effects before confirmation. Do not use fixture IDs in production.
Request
POST /api/developer-console/apps/{appId}/p2p-capabilities
Permission: app_topolo_developers.apps:write. Confirmation required. Validate against the current published action schema before preparing any actual request.
Inputs and behavior
| Field | Meaning in retained source |
|---|---|
| appId | Required selected-app ID; source checks app access. |
| capabilityId | Required for update; create generates a new ID. |
| name / description / category | Trimmed; lengths 2–120 / 10–2000 / 2–80. Create needs valid values despite loose schema. |
| inputSchema / outputSchema | Object-shaped definitions; non-object forms fall back to existing/default objects. |
| pricingModel / pricingAmountMinor / currency | free, fixed, metered, quote or invoice; amount integer ≥0; currency uppercase, first three characters then validated. |
| supportedContexts | human and/or agent; nonempty validated list. |
| trustLevel | standard, verified, trusted or restricted. |
| status | draft, approved, suspended or archived. |
The registered schema permits many loosely typed shared fields. This table describes the retained capability handler only; passing validation does not make irrelevant fields meaningful. publicDirectoryVisible and requiresHumanApproval are absent from this closed action schema even though the raw handler recognizes them.
Create requires completed developer onboarding; its explicit retained branch returns403, whereas the descriptor labels onboarding_incomplete409. The retained onboarding branch directly returns source-shaped {success:false,error:{message}} with no code/details, bypassing the shared catch. Exact localized text, raw capture and gateway/SDK envelopes remain unqualified.
The source trims name, description and category and checks lengths2–120,10–2000 and2–80 respectively. The registered input schema requires only appId and leaves these fields unconstrained; the minimal descriptor example can therefore pass local schema validation but fail source validation422.
A new capability ID is generated with prefix pcap. The supplied capabilityId is not used as the new ID. Retrying the create after an uncertain response can create another record; no idempotency key/deduplication contract is established.
Insert persists app/developer/publisher/workspace identity, schemas, pricing, visibility, status and generated revision. A subsequent read formats the returned record; formatting is qualified from the retained formatter.
The retained implementation attempts automatic sync when the saved capability is eligible. The descriptor claim that it remains invisible until a separate sync is unsafe. It can return an error after the local record is saved, and may have already published upstream.
The declared additionalProperties:false schema omits publicDirectoryVisible and requiresHumanApproval. Do not add them to an executable action input. On this retained source, a new record defaults publicDirectoryVisible false and requiresHumanApproval false; the raw route supports more fields than the registered action. This discrepancy needs owner disposition.
The route returns201 with the inner payload {capability,sync}; sync starts null and can become a delegated sync result. The helper envelope and local formatted capability are qualified; exact localized message text remains UNKNOWN.
The retained implementation gates synchronization on listingStatus approved, appStatus not archived, distributionModel marketplace, publicCatalogVisible, a nonblank app ID, capability status approved, and publicDirectoryVisible. The condition is not an exact appStatus active check.
Synchronization delegates from Developers to P2P with service scope capabilities.publish. Service identity is server-owned; it does not make this human-facing guide internal-only.
The service secret and client ID must be configured. Missing configuration can refuse with503. The source copies a downstream non-OK status through its ApiError handling; exact outer wire and current serving behavior are UNKNOWN.
P2P publication and local lastSyncedAt/lastSyncError updates are separate operations. A failed or lost response may follow a successful upstream publication. A local timestamp or null error alone does not prove the external directory outcome.
Worked examples
Declare a draft capability
SYNTHETIC / UNRUN.
{
"appId": "app_fixture_publisher",
"name": "Fixture stock lookup",
"description": "Read fictional stock counts for a fixture item.",
"category": "inventory",
"inputSchema": {
"type": "object",
"properties": {
"sku": {
"type": "string"
}
},
"required": [
"sku"
],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"available": {
"type": "integer"
}
},
"required": [
"available"
],
"additionalProperties": false
}
}
Assuming authorized completed onboarding, valid fixture publisher/workspace and accepted defaults, source persists then returns201. A complete synthetic success carrier appears below; its fixture message/IDs/timestamps are not observed values.
Locally valid but source-invalid minimal input
SYNTHETIC / UNRUN. Authorized completed-onboarding fixture app has valid publisher/workspace context; required content fields are absent. The source supplies those field flags, not a machine code.
Request:
{
"appId": "app_fixture_publisher"
}
Source-shaped raw HTTP 422 body (fixture message text, not a capture):
{
"success": false,
"error": {
"message": "FIXTURE localized validation message; exact literal unqualified",
"details": {
"name": true,
"description": true,
"category": true
}
}
}
This is the qualified serializer shape under the stated fixture assumptions. CLI/MCP wrapping and the current serving runtime were not exercised.
Incomplete onboarding
SYNTHETIC / UNRUN. The fixture developer onboarding state is incomplete. This explicit response bypasses the catch; no code/details argument is supplied.
Request:
{
"appId": "app_fixture_publisher",
"name": "Fixture lookup",
"description": "Illustrative fixture lookup operation.",
"category": "inventory"
}
Source-shaped raw HTTP 403 body (fixture message text, not a capture):
{
"success": false,
"error": {
"message": "FIXTURE localized onboarding-incomplete message; exact literal unqualified"
}
}
This is the qualified serializer shape under the stated fixture assumptions. CLI/MCP wrapping and the current serving runtime were not exercised.
Complete illustrative success response
SYNTHETIC / UNRUN. Message literal, identifiers and timestamps are fictional. The sync example includes a simulated upstream provider carrier; this is not a P2P schema or production receipt. Create/update fixture is not sync-eligible.
{
"success": true,
"message": "FIXTURE MESSAGE; actual localized literal not qualified",
"data": {
"capability": {
"capabilityId": "pcap_000000000001",
"appId": "app_fixture_publisher",
"developerId": "dev_fixture_publisher",
"publisherOrgId": "org_fixture_publisher",
"name": "Fixture stock lookup",
"description": "Read fictional stock counts for a fixture item.",
"category": "inventory",
"inputSchema": {
"type": "object",
"properties": {
"sku": {
"type": "string"
}
},
"required": [
"sku"
],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"available": {
"type": "integer"
}
},
"required": [
"available"
],
"additionalProperties": false
},
"pricingModel": "free",
"pricingAmountMinor": null,
"currency": null,
"requiresHumanApproval": false,
"supportedContexts": [
"human",
"agent"
],
"trustLevel": "standard",
"publicDirectoryVisible": false,
"status": "draft",
"sourceRevision": "rev_pcap_000000000001_1792738800",
"lastSyncedAt": null,
"lastSyncError": null,
"createdAt": "2026-10-23T07:00:00.000Z",
"updatedAt": "2026-10-23T07:00:00.000Z"
},
"sync": null
}
}
Verify and recover
Read the current published apps.p2p_capabilities.list contract and use the real selected app/capability identity. Compare the actual saved fields/source revision and last-sync status. A local list read alone does not prove external visibility.
When sync could have occurred, separately discover the authorized P2P read contract and verify the exact app/publisher/capability/revision there. No P2P endpoint or credential is inferred from this source-only packet.
After a failure/lost response, reconcile local record and external state before any retry. A create may already exist; a sync may already have published. Preserve exact request, IDs, original values and real response/request identifiers.
No automatic rollback is established across declaration persistence, P2P publication and sync-state recording. Reconcile both systems under their current owners; any approved corrective update may itself auto-sync. Do not follow generic retry-once or unsynced-is-private claims without current source-owner reconciliation.
All examples now include source-shaped response illustrations under explicit fixture assumptions. None is an actual capture. Message literals are fictional; one commerce-state detail is an explicit template value; the last sync failure chooses a specific generic Error branch. SDK/MCP wrappers and current serving behavior remain unqualified.
Contract provenance
Contract provenance: the retained raw application manifest declares permission apps:write and a generic object output schema. The separately captured credential-discovered descriptor at sourceRevision 7b89bd3b39092cdc29f87540847bf99a243f0a40 supplies the namespaced requiredPermission, static authorizationMode and a richer outputSchema marked derived-action-metadata / structural. This guide preserves that descriptor schema; the separate approved-profile production reads matched it at their recorded check. This is metadata association, not byte-equivalence to the raw manifest, a serving-Worker revision check, execution, P2P general availability, or a captured response. Source currentness beyond the pinned objects and serving behavior remain UNKNOWN.
Evidence and remaining gaps
Source: Topolo-io/TopoloDevelopers@7b89bd3b39092cdc29f87540847bf99a243f0a40:apps/api/functions/api/developer-console/app-integration-routes.ts and p2p-capabilities.ts. Source inspection is not a runtime test.
The formatter, http helpers and constants are qualified from retained immutable bytes. Formatter returns null on absent DB read; timestamps normalize to ISO strings or null, with created/updated fallbacks to current time. Synthetic timestamps are fixture values, not observed runtime.
The shared developer-console catch and errorResponse helper are source-qualified at pinned c6e543, unchanged from7b89. For the reviewed calls, ApiError status/message/details pass through and no code is supplied; plain Error maps to500/message only. Exact localized literals, SDK/gateway normalization, serving behavior and raw response captures remain unqualified.
Retained enums: pricing free/fixed/metered/quote/invoice; status draft/approved/suspended/archived; contexts human/agent; trust standard/verified/trusted/restricted. Pricing amount must be an integer>=0 when present; currency normalizes uppercase and truncates to three characters before the three-letter check.
Source-owner review and separate production descriptor/schema association are recorded. These establish source-reference documentation, not raw-manifest/derived-schema byte equivalence, serving runtime, P2P general availability or executed provider effects.
Changelog
2026-10-23 — Prepared a provisional guide from the retained source snapshot. Disclosed automatic-sync and error-status discrepancies. No product fix, live test or production publication is claimed.
2026-10-23 — Offline v3 copy correction: distinguish the capability-only 404 from unqualified app-access behavior where applicable, describe currency truncation as characters, and separate raw-manifest declarations from captured derived descriptor metadata. No schema/example rewrite, currentness, runtime result or publication is claimed.
2026-10-23 — Added seven source-shaped error response illustrations from the separately qualified shared serializer. Preserved all ten request inputs, the three normal success outputs and both schemas per action. No raw response capture, business execution, current serving claim or publication is asserted. 2026-10-23 — Reconciled the completed pinned source review and independent content acceptance; retained explicit runtime and execution limits. This changelog records documentation review, not a product release or executed P2P operation.