You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(spec,drivers): managed-datasource read-only is a database privilege, not a platform gate (#4584) (#7241)
* docs(spec,drivers): managed-datasource read-only is a database privilege, not a platform gate (#4584)
#4583 removed `datasource.capabilities.readOnly` — a key that read as a safety
property and gated nothing — and left the gap it exposed pointing at #4584:
`external.allowWrites: false` is the one enforced datasource-wide write gate and
it covers only FEDERATED datasources, so a managed datasource had no read-only
gate at all. #4584 ruled 方案 B: that stays so on purpose, and the docs say so.
An ObjectQL-level flag would stop writes on one path and leave a direct `psql`
session, a migration, a `syncSchema()` DDL statement and any process sharing the
connection string untouched. A boundary that holds in one path is not a
boundary, and one that merely looks like a boundary is worse than none because
it gets trusted — the exact defect #4583 removed. Read-only belongs to the
database account (`GRANT SELECT`), where there is no bypass surface.
Docs-only; no schema shape changes.
- content/docs/data-modeling/drivers.mdx: two new sections under
Multi-Datasource. "Read-only: grant it at the database, not in metadata" —
a worked `GRANT SELECT` role, the managed datasource that carries its
credentials in `config` (an `external` block is rejected there), the DDL /
schema-sync consequence of a read-only account, why the platform declines the
flag, and a table of what actually enforces what. "Read replicas: the platform
does not route" — the #4479 dual conclusion: no query path separates reads
from writes, so put the replicas behind pgpool / ProxySQL / an RDS reader
endpoint and point `config` there; that is the correct answer, not a stopgap.
- content/docs/data-modeling/external-datasources.mdx: the double opt-in write
gate now says plainly that it is federation-only, and links across.
- packages/spec/src/data/datasource.zod.ts: the `capabilities.readOnly`
tombstone carried "Tracked in #4584". It now carries the answer. Prose only —
no key, shape or default changed, and `check:docs` confirms no generated page
moves.
- examples/app-crm: the `crm_analytics` header comment recorded the ruling
instead of waiting on it.
Closes#4584
* docs(drivers): say "account", not "role", in the GRANT SELECT example (#4584)
The ADR-0090 D3 reserved-word ratchet (`check:role-word`) rejected two new uses
of "role" in the read-only section. Both are avoidable rather than genuine
boundaries, so this drops the word instead of taking a baseline waiver:
- prose: "at a role that can only read" → "at an account that can only read";
- SQL: `CREATE ROLE analytics_ro LOGIN PASSWORD …` → `CREATE USER analytics_ro
PASSWORD …`, which in PostgreSQL is exactly the same statement — `CREATE USER`
is `CREATE ROLE` with `LOGIN` implied — so the example is unchanged in effect.
`check:role-word` is green (44 baselined files, no new occurrences), as are
check:quick-reference-counts / adr-anchors / org-identifier / release-notes /
release-body and eslint over the changed sources.
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments