Skip to content

feat(spec): refuse ${…} placeholder syntax in connection-material driver config keys at publish (#8336) - #8457

Merged
qq9340100 merged 2 commits into
mainfrom
claude/issue-8336-placeholder-publish-refusal
Aug 13, 2026
Merged

feat(spec): refuse ${…} placeholder syntax in connection-material driver config keys at publish (#8336)#8457
qq9340100 merged 2 commits into
mainfrom
claude/issue-8336-placeholder-publish-refusal

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes#8336

Maintainer-ruled direction 2 (on-card comment, 2026-08-13): ${…} placeholder syntax in connection-material driver-config keys is refused at publish with explicit "placeholders are not resolved here" guidance pointing at the real escapes. Direction 1 (implement resolution) is rejected — no substitution is built.

The defect this closes

A placeholder in authored datasource config (e.g. config.url of postgresql://${DB_HOST}/db) is resolved by nothing — stored verbatim in sys_metadata, handed verbatim to the database client at connect (#7990 census, measured during #8078). The author believes environment substitution happens; the connection fails (or connects somewhere unintended) with no error naming the placeholder. Until now the syntax looked supported: parsed green, stored fine, failed at a distance.

What lands

Coverage

New driver-placeholder-refusal.test.ts: 20-key family table (refusal pathed at the key, code: 'custom', message asserts the ruling's guidance + escapes + carve-out; literal spelling accepted byte-identically; near-miss literals accepted), mongo options deep pins, DatasourceSchema re-path pin, no-contract boundary pin, #8082 composition pin (a URL violating both facts reports both). Envelope note (same as the #8082 pins): status does not exist at the schema layer — every schema refusal is wrapped uniformly by the publish door's 422 INVALID_METADATA (pinned generically in metadata-protocol, e.g. protocol.save-flow-canonicalization.test.ts asserting { code: 'INVALID_METADATA', status: 422 }); the zod issue's code and path are asserted here.

Runtime-environment DSNs (OS_DATABASE_URL and friends) never pass through this authoring schema and are unaffected by construction.

🤖 Generated with Claude Code

https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL

Generated by Claude Code


Generated by Claude Code

…ver config keys at publish (#8336)
The #7990 census (measured during #8078) established that ${…} placeholders
in authored datasource config are resolved by nothing — stored verbatim in
sys_metadata, handed verbatim to the database client, failing at a distance
with no error naming the placeholder. Two shipped refusal messages (#8078,
#8082) had to warn around the broken escape. Maintainer-ruled direction 2
(2026-08-13): refuse the syntax loudly at publish; direction 1 (implement
resolution) rejected — a capability with an env-exfiltration surface and no
measured pull.
- One shared value-level judgement in data/driver/common.zod.ts
(UNRESOLVED_PLACEHOLDER_REFUSED / containsUnresolvedPlaceholder /
placeholderFree / placeholderFreeDeep), the #8082 single-mechanism
construction, applied to every connection-material string key the shared
factory hands to the client: postgres url/host/database/username/schema/
applicationName, mysql url/host/database/username, mongo url/host/database/
username/authSource + the options passthrough (judged deep), turso
url/syncUrl/encryptionKey, sqlite + sqlite-wasm filename.
- Boundary: placeholder-by-intent — complete ${…} spans only; $VAR, {name},
unclosed ${ stay accepted; no-contract drivers stay unjudged (#4410 line).
- The #8082 message now points at the refusal instead of warning around it.
- #7990-census acceptance pins inverted, not deleted (datasource.test.ts,
postgres.test.ts); family pins in driver-placeholder-refusal.test.ts.
- ADR-0087: D3 semantic entry datasource-config-placeholder-refused (no D2 —
no mechanical rewrite exists); registry/spec-changes/upgrade-guide
regenerated. Changeset: @objectstack/spec minor (launch-window accept-set
narrowing).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
@vercel

vercelBot commented Aug 13, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 13, 2026 3:22pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

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

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @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/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via @objectstack/spec)
  • content/docs/automation/connectors.mdx(via @objectstack/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via 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/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 @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @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/tenancy-modes.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx(via @objectstack/spec)
  • 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/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/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via @objectstack/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx(via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx(via @objectstack/spec)
  • 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 @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/kernel/services.mdx(via @objectstack/spec)
  • content/docs/permissions/authorization.mdx(via @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/permissions/system-context.mdx(via packages/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @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/spec)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.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/ui/actions.mdx(via @objectstack/spec)
  • content/docs/ui/apps.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/field-grouping-and-order.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)

7 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/implementation-status.mdx(via @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • 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/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

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.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:data tests tooling labels Aug 13, 2026
gen:api-surface after rebuilding dist (the migration-registry regen had made
dist older than src, which the generator refuses — #7122/#4687). Adds the four
new data exports: UNRESOLVED_PLACEHOLDER_REFUSED, containsUnresolvedPlaceholder,
placeholderFree, placeholderFreeDeep.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
@qq9340100
qq9340100 marked this pull request as ready for review August 13, 2026 16:08
@qq9340100
qq9340100 added this pull request to the merge queueAug 13, 2026
Merged via the queue into main with commit 79021fcAug 13, 2026
27 checks passed
@qq9340100
qq9340100 deleted the claude/issue-8336-placeholder-publish-refusal branch August 13, 2026 16:25
qq9340100 pushed a commit that referenced this pull request Aug 13, 2026
…relay after #8457)
Discharges the os-regen deferral from the origin/main merge: api-surface,
export-origins, reference docs, strictness-ledger counts re-derived on the
merged base so the union carries both #8457's entries and the #8211
synonym-gate exports. gen:openapi re-run after the chain per the script's
warning. Sibling assertions green (datasource-config-placeholder-refused
registered; placeholderFree/containsUnresolvedPlaceholder body present).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationprotocol:datasize/lteststooling

Projects

None yet

2 participants

@qq9340100@claude