Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/error-code-provenance-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@objectstack/spec": patch
---

Error-code ledger: provenance rows and a provenance gate (#13353). Four adjudicated owner-key rows land for packages that already stamp registered codes on their own wire doors — `@objectstack/plugin-webhooks` / `INVALID_REQUEST`, `@objectstack/cloud-connection` / `FORBIDDEN`, `@objectstack/cli` / `ENVIRONMENT_NOT_FOUND`, `@objectstack/trigger-api` / `INVALID_REQUEST`. The registered union is unchanged (every code was already registered under another package), so `ErrorCode` accepts and rejects exactly what it did before — the rows are provenance only. A new mechanical gate (`check:error-code-provenance`) sweeps `packages/**` non-test source and fails any stamp site of a registered code the stamping package's own owner key does not list; deliberate "the door, not the producer, names the wire vocabulary" splits are recorded in the new exported `PROVENANCE_WAIVERS` table (with `ProvenanceWaiverSchema`), held live by the gate in both directions.
17 changes: 17 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,23 @@ jobs:
- name: Dispatcher error-code vocabulary guard
run: pnpm check:dispatcher-error-vocabulary

# #13353: the PROVENANCE half of the same ledger. The gate above reports
# codes the vocabulary does not contain; this one reports REGISTERED codes
# stamped by a package whose own owner key does not list them — the drift
# the ledger's admission rules structurally cannot see (they check casing,
# duplication and shadowing, never who emits), re-found by hand three
# times (#7504, #13254, #13353). Deliberate "the door, not the producer,
# names the wire vocabulary" splits are recorded in PROVENANCE_WAIVERS
# inside the ledger file and held live by the gate in both directions.
# Same placement rationale as its sibling above — no `paths:` filter,
# deliberately: the producers live in any package, and the rows live in
# packages/spec. It CANNOT ride the spec vitest suite instead: turbo
# hashes only per-package inputs, so a cached spec `test` run would stay
# green on exactly the PR that adds an unlisted stamper elsewhere.
# Runs its own --self-test first (wired into the package script).
- name: Error-code provenance guard
run: pnpm --filter @objectstack/spec check:error-code-provenance

# #10534 follow-up 4: a `rawApp` mount under the auth basePath with no ledger
# row. `auth-plugin.ts` mounts routes DIRECTLY on the raw Hono app, ahead of
# the better-auth catch-all, so the vendor's route table cannot account for
Expand Down
30 changes: 28 additions & 2 deletions content/docs/references/api/error-code-ledger.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ registration is a recorded waiver, never drift. A code registered NOWHERE
A code emitted by several packages is listed once per emitting package —
the union dedupes; the per-package rows are provenance, not identity.

Since #13353 that sentence has a mechanical half: the provenance gate
(`check:error-code-provenance`, `packages/spec/scripts/`) sweeps every
stamp site of a REGISTERED code in `packages/**` non-test source and fails
when the stamping package's own owner key does not list it. The admission
rules below never ask WHO emits, so before that gate an unlisted emitter was
invisible to every gate the repo has (three hand sweeps found the same class
three times: #7504, #13254, #13353). Two deliberate shapes are NOT rows and
are recorded in `PROVENANCE_WAIVERS` instead: a DOOR in another
package that names the wire vocabulary itself (`FLOW_DISABLED`,
`UPDATE_ID_MISMATCH` — see their rows' comments), and a shared constructor
package whose throw is served under another package's registration.

## Retiring a code

A row whose last EMITTER is deleted comes out with it. The admission rules
Expand Down Expand Up @@ -129,8 +141,8 @@ SEPARATE vocabulary and do not belong here — see #3977 (ADR-0112 D6).
## TypeScript Usage

```typescript
import { ErrorCode, StandardSynonymWaiverSchema } from '@objectstack/spec/api';
import type { ErrorCode, StandardSynonymWaiver } from '@objectstack/spec/api';
import { ErrorCode, ProvenanceWaiverSchema, StandardSynonymWaiverSchema } from '@objectstack/spec/api';
import type { ErrorCode, ProvenanceWaiver, StandardSynonymWaiver } from '@objectstack/spec/api';

// Validate data
const result = ErrorCode.parse(data);
Expand Down Expand Up @@ -442,6 +454,20 @@ const result = ErrorCode.parse(data);
* `WRONG_PASSWORD`


---

## ProvenanceWaiver

### Properties

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **package** | `string` | ✅ | The package whose source stamps the code without an owner-key row |
| **code** | `string` | ✅ | The registered code the package stamps |
| **registeredUnder** | `string` | ✅ | The owner key that deliberately carries the row instead |
| **reason** | `string` | ✅ | Why the stamping package carries no row — recorded so provenance is a decision, not drift |


---

## StandardSynonymWaiver
Expand Down
10 changes: 5 additions & 5 deletions content/docs/references/index.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Protocol Reference
description: Every schema published by @objectstack/spec — 1597 schemas across 14 protocol modules
description: Every schema published by @objectstack/spec — 1598 schemas across 14 protocol modules
---

{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
Expand All @@ -20,7 +20,7 @@ counts are sums of the rows they head. Regenerate with
| Module | Pages | Schemas | Description |
| :--- | ---: | ---: | :--- |
| [AI Protocol](/docs/references/ai) | 11 | 66 | Agents, tools, skills, RAG and knowledge sources, model registry, conversations. |
| [API Protocol](/docs/references/api) | 31 | 438 | REST contracts, endpoints, routing, realtime, batch, discovery. |
| [API Protocol](/docs/references/api) | 31 | 439 | REST contracts, endpoints, routing, realtime, batch, discovery. |
| [Automation Protocol](/docs/references/automation) | 13 | 68 | Flows and their nodes, approvals, ETL pipelines, webhooks, state machines, execution records. |
| [Cloud Protocol](/docs/references/cloud) | 11 | 94 | Environments, packages and versions, marketplace, developer portal, tenancy. |
| [Data Protocol](/docs/references/data) | 29 | 166 | Objects, fields, queries, filters, datasources and drivers — the ObjectQL layer. |
Expand All @@ -33,7 +33,7 @@ counts are sums of the rows they head. Regenerate with
| [Studio Protocol](/docs/references/studio) | 3 | 35 | Studio designer metadata — the authoring surfaces for the protocols above. |
| [System Protocol](/docs/references/system) | 36 | 291 | The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance. |
| [UI Protocol](/docs/references/ui) | 16 | 153 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. |
| **Total** | **200** | **1597** | 14 protocol modules |
| **Total** | **200** | **1598** | 14 protocol modules |

---

Expand Down Expand Up @@ -61,7 +61,7 @@ Agents, tools, skills, RAG and knowledge sources, model registry, conversations.

## API Protocol

**Source:** `packages/spec/src/api/` · **Import:** `@objectstack/spec/api` · **31 pages, 438 schemas**
**Source:** `packages/spec/src/api/` · **Import:** `@objectstack/spec/api` · **31 pages, 439 schemas**

REST contracts, endpoints, routing, realtime, batch, discovery.

Expand All @@ -77,7 +77,7 @@ REST contracts, endpoints, routing, realtime, batch, discovery.
| [`dispatcher.zod.ts`](/docs/references/api/dispatcher) | `DispatcherConfig`, `DispatcherErrorCode`, `DispatcherErrorResponse`, `DispatcherRoute` |
| [`documentation.zod.ts`](/docs/references/api/documentation) | `ApiChangelogEntry`, `ApiDocumentationConfig`, `ApiTestCollection`, `ApiTestRequest`, `ApiTestingUiConfig`, `ApiTestingUiType`, `CodeGenerationTemplate`, `GeneratedApiDocumentation`, `OpenApiSecurityScheme`, `OpenApiServer`, `OpenApiSpec` |
| [`endpoint.zod.ts`](/docs/references/api/endpoint) | `ApiEndpoint`, `ApiMapping` |
| [`error-code-ledger.zod.ts`](/docs/references/api/error-code-ledger) | `ErrorCode`, `StandardSynonymWaiver` |
| [`error-code-ledger.zod.ts`](/docs/references/api/error-code-ledger) | `ErrorCode`, `ProvenanceWaiver`, `StandardSynonymWaiver` |
| [`errors.zod.ts`](/docs/references/api/errors) | `EnhancedApiError`, `ErrorCategory`, `ErrorResponse`, `FieldError`, `FieldErrorCode`, `RetryStrategy`, `StandardErrorCode` |
| [`events.zod.ts`](/docs/references/api/events) | `BulkDataEvent`, `BulkDataEventType`, `DataEvent`, `DataEventType`, `MetadataEvent`, `MetadataEventType` |
| [`export.zod.ts`](/docs/references/api/export) | `CreateExportJobRequest`, `CreateExportJobResponse`, `CreateImportJobRequest`, `CreateImportJobResponse`, `DeduplicationStrategy`, `ExportFormat`, `ExportImportTemplate`, `ExportJobProgress`, `ExportJobStatus`, `ExportJobSummary`, `FieldMappingEntry`, `GetExportJobDownloadRequest`, `GetExportJobDownloadResponse`, `ImportJobProgress`, `ImportJobResults`, `ImportJobStatus`, `ImportJobSummary`, `ImportMapping`, `ImportRequest`, `ImportResponse`, `ImportRowResult`, `ImportValidationConfig`, `ImportValidationMode`, `ImportValidationResult`, `ImportWriteMode`, `ListExportJobsRequest`, `ListExportJobsResponse`, `ListImportJobsRequest`, `ListImportJobsResponse`, `ScheduleExportRequest`, `ScheduleExportResponse`, `ScheduledExport`, `UndoImportJobResponse` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ directory rather than per file.
| Dir | Sites |
|---|---|
| `ai/` | 77 |
| `api/` | 453 |
| `api/` | 454 |
| `cloud/` | 83 |
| `identity/` | 32 |
| `integration/` | 10 |
Expand Down
3 changes: 3 additions & 0 deletions packages/spec/api-surface/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@
"OpenApiSpecSchema (const)",
"OperatorMapping (type)",
"OperatorMappingSchema (const)",
"PROVENANCE_WAIVERS (const)",
"PackageApiContracts (const)",
"PackageApiErrorCode (type)",
"PackageExportManifest (type)",
Expand Down Expand Up @@ -767,6 +768,8 @@
"PresignedUrlResponse (type)",
"PresignedUrlResponseParsed (type)",
"PresignedUrlResponseSchema (const)",
"ProvenanceWaiver (type)",
"ProvenanceWaiverSchema (const)",
"PublishMetaItemRequest (type)",
"PublishMetaItemRequestSchema (const)",
"PublishMetaItemResponse (type)",
Expand Down
4 changes: 4 additions & 0 deletions packages/spec/authorable-surface/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,10 @@
"api/PresignedUrlResponse:error",
"api/PresignedUrlResponse:meta",
"api/PresignedUrlResponse:success",
"api/ProvenanceWaiver:code",
"api/ProvenanceWaiver:package",
"api/ProvenanceWaiver:reason",
"api/ProvenanceWaiver:registeredUnder",
"api/PublishMetaItemRequest:actor",
"api/PublishMetaItemRequest:message",
"api/PublishMetaItemRequest:name",
Expand Down
2 changes: 2 additions & 0 deletions packages/spec/declaration-map/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,8 @@
"PresenceUpdateSchema": "api/PresenceUpdate",
"PresignedUrlResponse": "api/PresignedUrlResponse",
"PresignedUrlResponseSchema": "api/PresignedUrlResponse",
"ProvenanceWaiver": "api/ProvenanceWaiver",
"ProvenanceWaiverSchema": "api/ProvenanceWaiver",
"PublishMetaItemRequest": "api/PublishMetaItemRequest",
"PublishMetaItemRequestSchema": "api/PublishMetaItemRequest",
"PublishMetaItemResponse": "api/PublishMetaItemResponse",
Expand Down
3 changes: 3 additions & 0 deletions packages/spec/export-origins/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@
"OpenApiSpecSchema": "src/api/documentation.zod.ts#OpenApiSpecSchema (const)",
"OperatorMapping": "src/api/query-adapter.zod.ts#OperatorMapping (type)",
"OperatorMappingSchema": "src/api/query-adapter.zod.ts#OperatorMappingSchema (const)",
"PROVENANCE_WAIVERS": "src/api/error-code-ledger.zod.ts#PROVENANCE_WAIVERS (const)",
"PackageApiContracts": "src/api/package-api.zod.ts#PackageApiContracts (const)",
"PackageApiErrorCode": "src/api/package-api.zod.ts#PackageApiErrorCode (type)",
"PackageExportManifest": "src/api/package-lifecycle.zod.ts#PackageExportManifest (type)",
Expand Down Expand Up @@ -767,6 +768,8 @@
"PresignedUrlResponse": "src/api/storage.zod.ts#PresignedUrlResponse (type)",
"PresignedUrlResponseParsed": "src/api/storage.zod.ts#PresignedUrlResponseParsed (type)",
"PresignedUrlResponseSchema": "src/api/storage.zod.ts#PresignedUrlResponseSchema (const)",
"ProvenanceWaiver": "src/api/error-code-ledger.zod.ts#ProvenanceWaiver (type)",
"ProvenanceWaiverSchema": "src/api/error-code-ledger.zod.ts#ProvenanceWaiverSchema (const)",
"PublishMetaItemRequest": "src/api/protocol.zod.ts#PublishMetaItemRequest (type)",
"PublishMetaItemRequestSchema": "src/api/protocol.zod.ts#PublishMetaItemRequestSchema (const)",
"PublishMetaItemResponse": "src/api/protocol.zod.ts#PublishMetaItemResponse (type)",
Expand Down
1 change: 1 addition & 0 deletions packages/spec/json-schema.manifest/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@
"api/PresenceStatus",
"api/PresenceUpdate",
"api/PresignedUrlResponse",
"api/ProvenanceWaiver",
"api/PublishMetaItemRequest",
"api/PublishMetaItemResponse",
"api/PublishPackageDraftsResponse",
Expand Down
1 change: 1 addition & 0 deletions packages/spec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@
"gen:liveness-counts": "tsx scripts/liveness/build-state-counts.mts",
"check:empty-state": "tsx scripts/liveness/check-empty-state.mts",
"check:variant-docs": "tsx scripts/check-variant-docs.mts",
"check:error-code-provenance": "tsx scripts/check-error-code-provenance.ts --self-test && tsx scripts/check-error-code-provenance.ts",
"gen:strictness-ledger": "tsx scripts/build-strictness-ledger-counts.mts",
"check:strictness-ledger": "tsx scripts/check-strictness-ledger.mts",
"gen:react-blocks": "tsx scripts/build-react-blocks-contract.ts",
Expand Down
Loading
Loading