Outcome
Read saved application assurance submissions and their latest decision projections in the owning workspace, keeping historical evidence separate from current release assurance.
GET /api/developer-console/apps/{appId}/assurance
Before you start
Use the original organization, published apps:read permission and separately discovered canonical Developers workspace at required read access. Resolve the accessible app through supported reads; never infer access from an app id or assurance record.
This owner route calls ordinary workspace context resolution without the suspended-read opt-in used by some other Developers GET routes. Suspended/revoked contexts remain refused; app/workspace/actor read access and an additional service permission check apply. Archived apps return404. Shared context may initialize a local profile/mirror before later refusal, so a read-only declaration is not a no-write guarantee for the whole pipeline.
Examples are complete synthetic UNRUN stored-state carriers with fictional identities. No actual assurance/private record, app, reviewer or security attestation was read/submitted/approved; no app import/test/runtime probe was executed.
Request and response
Action: app_topolo_developers.apps.assurance.list.
GET returns the full {success:true,message,data:{application,records,limit:100}} envelope. application contains current appId,organizationId,workspaceId and normalized current repository. records contains saved immutable submissions joined to their latest appended decision; there is no top-level app array, total count or nextCursor in this handler.
Input is appId plus optional sourceRevision matching exactly40 lower-case hexadecimal characters. Omit the revision to list available saved revisions; supplied revision filters exact equality, not a prefix, branch, range or current HEAD alias. No limit/cursor/status filter is implemented by this contract.
The owner query restricts app id plus the current app organization and workspace. It sorts submitted_at descending then id descending and returns at most100 rows. limit:100 reports the fixed cap, not actual row count, total inventory or proof no older records exist. No supported pagination is exposed here.
Each record includes id,appId,organizationId,workspaceId,repository,sourceRevision,attestationJson,contentHash,submittedBy,submittedAt,version,status,reviewedBy,reviewedAt,reason. With no decision the projection uses version0,statuspending and null review fields. Later decisions are selected by maximum version, not by claiming the submission itself was edited.
attestationJson is stored JSON text, not an automatically parsed system object. This read does not validate the attestation again, recompute its content hash, fetch the repository, execute a security test, prove reviewer independence or establish deployed-source identity. Treat raw text as data and inspect exact record provenance before relying on it.
The application repository is normalized from the current app record using HTTPS/no credentials/query/fragment and a two-segment path, stripping trailing slash/.git and lowercasing. Invalid current repository becomes null. This is normalization, not a GitHub-only or repository-ownership certificate.
The owner list filters current organization/workspace but does not filter each saved row to the current repository. The response can therefore show historical saved repository/source facts beside a changed current application repository. Compare those identities explicitly; do not promote any historical approved status to blanket current release or enterprise assurance.
Owner reads and the separately authorized marketplace review route have different access paths. Do not switch to a reviewer endpoint to evade an owner-route refusal. This GET makes no approval, revocation, submission or profile-permission grant.
Worked requests and responses
No saved records match the app
Complete synthetic UNRUN HTTP200 assuming accessible active context/app and no matching saved rows. limit100 is the fixed cap. Empty history is not security approval or proof a different repository/workspace has no record.
Input:
{
"appId": "app_docs_fixture"
}
Response:
{
"success": true,
"message": "OK",
"data": {
"application": {
"appId": "app_docs_fixture",
"organizationId": "org_docs_fixture",
"workspaceId": "ws_docs_fixture",
"repository": "https://github.com/fixture/example"
},
"records": [],
"limit": 100
}
}
Inspect the actual empty records and exact current app/owner/workspace; do not fabricate evidence.
Read a stored pending record for one exact revision
Complete synthetic UNRUN HTTP200 assuming this exact opaque illustrative string was already saved as a row. It deliberately is not a submittable system/attestation example: this list projects stored text without revalidation. Hash is SHA256 of those exact illustrative UTF8 bytes. No submission/security approval/private read was performed.
Input:
{
"appId": "app_docs_fixture",
"sourceRevision": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
Response:
{
"success": true,
"message": "OK",
"data": {
"application": {
"appId": "app_docs_fixture",
"organizationId": "org_docs_fixture",
"workspaceId": "ws_docs_fixture",
"repository": "https://github.com/fixture/example"
},
"records": [
{
"id": "00000000-0000-4000-8000-000000000001",
"appId": "app_docs_fixture",
"organizationId": "org_docs_fixture",
"workspaceId": "ws_docs_fixture",
"repository": "https://github.com/fixture/example",
"sourceRevision": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"attestationJson": "{\"example\":\"synthetic unrun stored evidence; not a submittable system\"}",
"contentHash": "f8818a2a18e6928b952699ae9269f812bfd594abcf987037266eee4f311fe269",
"submittedBy": "usr_docs_fixture",
"submittedAt": "2026-10-21T00:00:00.000Z",
"version": 0,
"status": "pending",
"reviewedBy": null,
"reviewedAt": null,
"reason": null
}
],
"limit": 100
}
}
Compare saved app/org/workspace/repository/revision/hash and pending version0/null review facts. Parse only as data; this example grants no assurance or submission validity.
An archived app is not returned
Complete synthetic UNRUN rawHTTP404 assuming prior owner permission/access passes and the current app is archived. No assurance query is reached. Shared context initialization is separate.
Input:
{
"appId": "app_docs_fixture"
}
Response:
{
"success": false,
"error": {
"message": "Developer app not found",
"code": "not_found"
}
}
Respect the actual archived/app access state; do not substitute a reviewer route or another workspace.
Verify and recover
-
Verify application identity/current repository and each selected record owner/workspace/repository/sourceRevision. Use exact id+version+contentHash rather than title or maximum-version assumptions across different submissions.
-
For meaningful evidence, compare the saved exact attestation text/hash against legitimate source artifacts and reviewer decision/provenance under their existing owners. A read response, approved status or source hash alone is not current runtime/security/deployment certification.
-
If100 rows are returned, do not infer complete history. Use an exact known sourceRevision filter where appropriate; if a complete paginated history is required, record the missing supported capability instead of inventing cursor/limit fields or accessing another authorization path.
-
No inverse is needed for the selected assurance query; possible earlier shared profile/mirror initialization is separate and has no rollback in this action. On refusal/uncertainty retain exact context and request details rather than bypassing access.
Change log
- 2026-10-21: Added exact owner/revision filtering, fixed100-row limit, saved text/hash and latest-decision projection, repository/history and authorization boundaries, with complete synthetic unrun examples.