Skip to content

feat(spec,core,runtime,docs)!: ADR-0112 batch 1 — one error-code vocabulary, SCREAMING_SNAKE, schema-enforced (#3841) - #3988

Merged
os-zhuang merged 4 commits into
mainfrom
claude/error-code-vocabulary-mismatch-iscrkw
Jul 30, 2026
Merged

feat(spec,core,runtime,docs)!: ADR-0112 batch 1 — one error-code vocabulary, SCREAMING_SNAKE, schema-enforced (#3841)#3988
os-zhuang merged 4 commits into
mainfrom
claude/error-code-vocabulary-mismatch-iscrkw

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Implements batch 1 of ADR-0112's Rollout (settling #3841).

What

Interplay with #3842 (landed mid-flight)

#3842 moved the semantic code into error.code and left HttpStatusErrorCodeMap as the deliberate one-file sweep point for this decision ("#3841 owns reconciling the two"). This PR is that sweep: derived codes change case on the wire (permission_deniedPERMISSION_DENIED, etc.). Per the batch-1 consumer check (and the ADR's harvest), no in-repo consumer branches on the lowercase spellings; every existing consumer branch (console attachment panel, dogfood suite, client tests) reads codes this PR leaves byte-identical.

Deviations from the ADR letter (recorded)

  1. D7 (generated catalog): the catalog page keeps its hand-written Cause/Fix prose; a new spec test (error-catalog-docs.test.ts) locks its headings 1:1 to the enum instead of full generation — the drift-proofing without losing the prose. The schema-level reference (references/api/errors.mdx) remains fully generated.
    1. Ledger summaries: mechanical harvest entries carry // one-liners only where the name doesn't speak for itself, rather than a mandatory summary field.

Test evidence

Suite Result
spec (full) 265 files / 6880 ✅
runtime (full) 65 files / 888 ✅
rest (full) 30 files / 440 ✅
core (full)
service-storage / service-i18n 222 / 63 ✅
client (full) 196 ✅
qa/http-conformance 41 ✅

Follow-ups (not this PR)

Closes #3841.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MaSQn77TT5fUgHK9CesaDK


Generated by Claude Code

…bulary, SCREAMING_SNAKE, schema-enforced (#3841)

- Rename all 53 StandardErrorCode members to SCREAMING_SNAKE in place;
  HttpStatusErrorCodeMap (#3842's designated sweep point) follows, so
  derived wire codes change case (permission_denied -> PERMISSION_DENIED).
- Add ERROR_CODE_LEDGER (spec/api/error-code-ledger.zod.ts): 130+ service
  codes registered per owning package, harvested from every non-test
  emitter; ErrorCode = StandardErrorCode ∪ registered.
- Tighten ApiErrorSchema.code from z.string() to ErrorCode — the envelope
  conformance suites now assert values, not just shape.
- Widen FieldErrorSchema.code to z.string() (ADR-0112 D6): field-level
  codes are a separate vocabulary; #3977 owns its catalog.
- ANONYMOUS_DENY_CODE 'unauthenticated' -> 'UNAUTHENTICATED' (promoted
  into error.code on the dispatcher surface, so it must be catalogued).
- Rewrite error-catalog.mdx to the two-tier model and lock its headings
  to the enum with a new spec test; update the error-handling guides.
- Regenerate json-schema manifest, api-surface, docs references.

Batches 2 (lowercase emitter sweep) and 3 remain per the ADR's Rollout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MaSQn77TT5fUgHK9CesaDK
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 30, 2026 1:12am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/xl labels Jul 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/core, @objectstack/rest, @objectstack/runtime, @objectstack/spec.

120 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/actions-as-tools.mdx (via @objectstack/core)
  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/knowledge-rag.mdx (via @objectstack/core)
  • content/docs/ai/natural-language-queries.mdx (via @objectstack/core)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via packages/runtime, @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/rest, @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/rest, @objectstack/runtime, @objectstack/spec)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/runtime, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/core, packages/runtime, packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/migration-from-objectql.mdx (via @objectstack/core)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/core)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/core)
  • content/docs/permissions/authentication.mdx (via @objectstack/core, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/core, packages/runtime, @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/anatomy.mdx (via @objectstack/core)
  • content/docs/plugins/development.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/core, @objectstack/rest, @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/core, @objectstack/rest, @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/rest, @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/core, @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/core, @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/core, @objectstack/rest, @objectstack/runtime, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/core, @objectstack/rest, @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v15.mdx (via @objectstack/core)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

claude added 3 commits July 30, 2026 01:09
…erived-code casing in api index

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MaSQn77TT5fUgHK9CesaDK
… ADR-0112 casing

check:skill-refs and check:skill-examples gates — the skill reference
index derives from spec schemas (new error-code-ledger page), and the
prose-example compiler caught one remaining lowercase member literal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MaSQn77TT5fUgHK9CesaDK
@os-zhuang
os-zhuang marked this pull request as ready for review July 30, 2026 01:42
@os-zhuang
os-zhuang merged commit 32ccb23 into main Jul 30, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/error-code-vocabulary-mismatch-iscrkw branch July 30, 2026 01:42
os-zhuang pushed a commit that referenced this pull request Jul 30, 2026
…nd refresh the console pin (#3843)

Merging main brought in ADR-0112 batch 1 (#3841 (#3988)) and #3842, both of
which landed while this PR was in review. Two of this PR's stated decisions were
premised on #3841 being UNDECIDED, so they no longer hold.

`ApiErrorSchema.code` is now the closed `ErrorCode` union, not `z.string()`, so
the nine lowercase codes this PR deliberately carried over failed schema parse —
which failed its own conformance suites (6 in service-datasource, 1 in
service-settings). Re-spelled per ADR-0112, with generic conditions going to the
STANDARD catalog rather than becoming registered synonyms of it, which is what
the ledger asks for:

  datasource_admin_unavailable  → SERVICE_UNAVAILABLE      (standard)
  external_service_unavailable  → SERVICE_UNAVAILABLE      (standard)
  not_found / PACKAGE_NOT_FOUND → RESOURCE_NOT_FOUND       (standard)
  PUBLISH_FIELDS_MISSING        → MISSING_REQUIRED_FIELD   (standard)
  INTERNAL                      → INTERNAL_ERROR           (standard)
  datasource_admin_error        → DATASOURCE_ADMIN_ERROR   (registered)
  external_import_error         → EXTERNAL_IMPORT_ERROR    (registered)
  PUBLISH_MANIFEST_INVALID      → PACKAGE_MANIFEST_INVALID (registered)
  PUBLISH_FAILED                → PACKAGE_PUBLISH_FAILED   (registered)
  PACKAGE_DELETE_PARTIAL / PACKAGE_DELETE_FAILED / SETTINGS_ACTION_FAILED

Which service is unavailable is carried by `message` — the ledger explicitly
asks generic conditions to reuse the catalog instead of registering a per-service
503. The seven registered codes go into ERROR_CODE_LEDGER under their owning
packages, including a new @objectstack/service-datasource entry.

Also bumps .objectui-sha a136322 → e651c93 now that objectui#2972 has merged, so
the bundled Setup console carries the envelope tolerance this change needs. The
pin only moves two commits because main had already refreshed it to a136322 —
an earlier attempt from this branch's stale base would have swept in eleven
unrelated frontend commits including two breaking ones.

The route-envelope guard, the conformance suites and their doc comments are
updated to match. Guard: 8 modules, 5 conformant / 2 ratcheted / 1 exempt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CYbS3kS8xzsHNXFTzp4e2z
os-zhuang pushed a commit that referenced this pull request Jul 30, 2026
…nd refresh the console pin (#3843)

Merging main brought in ADR-0112 batch 1 (#3841 (#3988)) and #3842, both of
which landed while this PR was in review. Two of this PR's stated decisions were
premised on #3841 being UNDECIDED, so they no longer hold.

`ApiErrorSchema.code` is now the closed `ErrorCode` union, not `z.string()`, so
the nine lowercase codes this PR deliberately carried over failed schema parse —
which failed its own conformance suites (6 in service-datasource, 1 in
service-settings). Re-spelled per ADR-0112, with generic conditions going to the
STANDARD catalog rather than becoming registered synonyms of it, which is what
the ledger asks for:

  datasource_admin_unavailable  → SERVICE_UNAVAILABLE      (standard)
  external_service_unavailable  → SERVICE_UNAVAILABLE      (standard)
  not_found / PACKAGE_NOT_FOUND → RESOURCE_NOT_FOUND       (standard)
  PUBLISH_FIELDS_MISSING        → MISSING_REQUIRED_FIELD   (standard)
  INTERNAL                      → INTERNAL_ERROR           (standard)
  datasource_admin_error        → DATASOURCE_ADMIN_ERROR   (registered)
  external_import_error         → EXTERNAL_IMPORT_ERROR    (registered)
  PUBLISH_MANIFEST_INVALID      → PACKAGE_MANIFEST_INVALID (registered)
  PUBLISH_FAILED                → PACKAGE_PUBLISH_FAILED   (registered)
  PACKAGE_DELETE_PARTIAL / PACKAGE_DELETE_FAILED / SETTINGS_ACTION_FAILED

Which service is unavailable is carried by `message` — the ledger explicitly
asks generic conditions to reuse the catalog instead of registering a per-service
503. The seven registered codes go into ERROR_CODE_LEDGER under their owning
packages, including a new @objectstack/service-datasource entry.

Also bumps .objectui-sha a136322 → e651c93 now that objectui#2972 has merged, so
the bundled Setup console carries the envelope tolerance this change needs. The
pin only moves two commits because main had already refreshed it to a136322 —
an earlier attempt from this branch's stale base would have swept in eleven
unrelated frontend commits including two breaking ones.

The route-envelope guard, the conformance suites and their doc comments are
updated to match. Guard: 8 modules, 5 conformant / 2 ratcheted / 1 exempt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CYbS3kS8xzsHNXFTzp4e2z
os-zhuang added a commit that referenced this pull request Jul 30, 2026
…ode vocabulary (#3843 follow-up) (#4009)

Comment-only follow-up to #3972 (#3843). No behaviour change.

Two sentences in package-envelope.conformance.test.ts's header were written while
#3841 was still undecided, and #3843 landed after ADR-0112 settled it:

  - "why #3841 still owns the vocabulary" — it does not; ADR-0112 (#3988) closed
    it and ApiErrorSchema.code is a closed union now.
  - "this module needed MINTED codes" — half true. It had nothing to carry over
    (its `error` strings were human messages), but only four of the codes here are
    registered; the three generic conditions reuse the standard catalog, which is
    what the ledger asks for.

Rewritten to state the actual split and why it makes the assertions below
load-bearing: an unregistered code fails parse, so BaseResponseSchema.safeParse is
what would catch an invented one. package-routes.ts already carried the corrected
note; this was the test file missed beside it.

Carries an empty changeset — the PR gate requires one, and this releases nothing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Two error-code vocabularies are both live: StandardErrorCode is lowercase snake_case, the servers emit SCREAMING_SNAKE

2 participants