Repository navigation
Commit fb69825
fix(spec): datasource read redaction resolves a driver's identity the way its sibling helper does (#21963)
Fixes #21955
Clause-②: no
## What changed
The per-driver half of `redactableConfigKeys` in
`packages/spec/src/data/datasource-credential-redaction.ts` now resolves
a driver's identity through `resolveDriverId`. That is the resolver its
sibling helper `passthroughSecretPaths` already uses, and the one the
write door's contract lookup (`getDriverConfigSchema`) uses. There is no
second identity resolver: the fix replaces one lookup line with the
sibling's two-line shape.
- Every spelling the write door judges against a builtin driver's
contract is now redacted as that driver. The still-writable credential
key is withheld on the datasource admin item read and on the metadata
read under every accepted spelling, and `redactedConfigKeys` names it.
- A crafted driver id now has a defined answer. It resolves to no
builtin, so it answers as a driver the platform ships no contract for:
the canonical credential spellings and the former aliases are withheld,
and the read succeeds. It is never served and never throws.
- No `service-datasource` source line moves. `getDatasource()`,
`restoreRedactedConfig` and the credential migration all reach the fix
through the spec export (measured below).
## Measured reach, before the fix (BASE `76fec88b16`, spec dist built
from BASE)
A unit-level harness of `service-datasource`'s `DatasourceAdminService`,
with an in-memory record store, ran every spelling the alias table and
the resolver's folding accept. The harness is scratch and is not
committed.
- **Write door:** every accepted spelling was accepted by
`DatasourceSchema.safeParse` and by `createDatasource`, and was judged
against the builtin contract (`validateDriverConfig(...).known ===
true`).
- **Admin item read** (`getDatasource`, behind `GET
/api/v1/datasources/:name`): for each accepted spelling other than the
canonical one, the still-writable credential key came back in `config`
and `redactedConfigKeys` was `[]`. The canonical spelling withheld it.
- **Metadata read** (the built-in `datasource` redactor, used by the
`/meta` item and list reads): the same answer as the item read for every
spelling.
- **Admin list read** (`listDatasources`): it serves no `config` at all,
by its contract (`DatasourceSummary`), so it carries no exposure for any
spelling.
- **Crafted driver id:** the write door accepted the row as an unknown
plugin driver. Then `getDatasource`, the metadata redactor,
`restoreRedactedConfig` and `planCredentialMigration` each threw an
unhandled `TypeError`. So the item read failed, an edit with a config
patch failed, and the migration planner failed. `listDatasources` was
unaffected.
After the fix, the same harness reads every accepted spelling as
withheld and named, and every crafted id as read without a throw.
Exposure stays admin-only: the datasource read doors require the admin
capability.
## Pins
- `packages/spec/src/data/datasource-credential-redaction.test.ts`, a
new block. Every spelling is derived from `DRIVER_ID_ALIASES` plus the
resolver's own folding (as-is, upper, capitalised, padded), never listed
by hand.
- Premise: each accepted spelling resolves to its builtin and is judged
by the write door against that contract.
- Each accepted spelling answers its canonical driver's redactable set,
byte-equal.
- The still-writable credential key is withheld under each accepted
spelling and named as withheld. It has a population floor, so a
derivation that finds nothing fails.
- Control: a canonical spelling withholds it exactly as before.
- A crafted driver id answers as a driver with no shipped contract, with
credentials withheld and no throw.
- Lockstep in `service-datasource` (declared on #6021):
- `datasource-config-redaction.test.ts`: the admin item read withholds
the key under each accepted spelling. An untouched Save restores the
stored value under each accepted spelling, so redaction never turns a
save into deletion. A crafted id is read with its credentials withheld,
and an untouched Save keeps them.
- `datasource-credential-migration.test.ts`: the planner reads the same
list under each accepted spelling. A bindable row names the
still-writable key as residue, byte-equal to the canonical spelling's
plan. A row holding only that key is refused with it named.
### Reverse verification (fix committed first, then reverted with
`scripts/ablation-replace.mjs`, then restored)
- **Spec pin.** The subject is imported relatively from `src`, so no
build leg applies. Predicted three red, with the premise and the control
staying green. Observed `Tests 3 failed | 41 passed (44)`: the
byte-equal set, the withheld key, and the crafted id. Restore proof:
blob `b543590328ef` equals HEAD, and `git diff HEAD` is empty.
- **`service-datasource` pins.** These resolve `@objectstack/spec/data`
through `dist`, so each leg rebuilt spec.
- Mutate leg: `ablation-dist-preflight` found the reverted line in 8
built files. Predicted five red. Observed `Tests 5 failed | 61 passed
(66)`.
- Restore leg: rebuild, then `--absent` reported the marker absent from
all 228 built files and the tree clean against HEAD. Then `Tests 66
passed (66)`.
## Clause-② (measured)
`no`. The fix narrows what the read path serves, not what
`@objectstack/spec` accepts.
- No schema file changed. `DatasourceSchema.safeParse` gave the same
answer before and after for every spelling and every crafted id in the
harness.
- `check:api-surface`: `public API surface + factory signatures
unchanged`.
- `check:authorable-surface` and `check:export-origins` are green.
The changeset is `@objectstack/spec` `patch`. `service-datasource` takes
none, because no source line in it moved.
## Tests and gates (at HEAD `cbea11408e`)
- `pnpm --filter @objectstack/spec exec vitest run --project local
--maxWorkers=2`: `Test Files 619 passed (619)`, `Tests 18476 passed | 1
todo`.
- `pnpm --filter @objectstack/service-datasource exec vitest run
--maxWorkers=2`: `Test Files 41 passed (41)`, `Tests 748 passed (748)`.
- `@objectstack/metadata-protocol`, which reaches the datasource
redactor: `protocol.metadata-redaction.test.ts` and
`stored-metadata-body-family.pin.test.ts` gave `Tests 56 passed (56)`.
- `pnpm --filter @objectstack/service-datasource typecheck` and `pnpm
--filter @objectstack/spec typecheck` (including `check:test-typecheck`)
both exit 0. `tsc --listFiles` confirms that both edited
`service-datasource` test files are in the program.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`: 87 derived, 86 run with exit 0, 1 NOT
MEASURED, 0 unrun (`--ran` reconciliation).
- NOT MEASURED: `pnpm check:dual-build-cjs-loads`, reason: PREREQUISITE
NOT MET (exit 3). It reads every package's built `dist/`, and this
worktree built only the closure it needed. Declared to CI.
- Lint is a proven narrowing, not the repo-wide run.
- ① The checked population is the four touched `.ts` files. Each
resolves to a config under `eslint --print-config`, so none is ignored.
- ② `eslint --no-inline-config --format json` linted 4 files with 0
errors and 0 warnings.
- ③ Invariance: `eslint.config.mjs` enables no type-aware linting (zero
`project` / `projectService` entries, and none in the resolved
`parserOptions`). So this diff cannot move any untouched file's verdict.
- The repo-wide `pnpm lint` stays CI's.
- `origin/main` was re-fetched before this PR opened (`80f9f7e6ba`).
Nothing that landed since BASE touches these files, so there was no
merge.
## Acceptance notes
- `STILL_WRITABLE_CREDENTIAL_KEYS` and `PASSTHROUGH_SECRET_PATHS` are
typed as string-keyed records. Typing them by the builtin id union would
make a raw-string index a compile error, closing this defect class at
`tsc`. That is not done here, to keep the fix to the sibling's shape.
Carrier: the at-tier contract review of this PR.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 787104b commit fb69825
5 files changed
Lines changed: 236 additions & 3 deletions
File tree
- .changeset
- packages
- services/service-datasource/src/__tests__
- spec/src/data
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
| 42 | + | |
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| |||
603 | 603 | | |
604 | 604 | | |
605 | 605 | | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
| 19 | + | |
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| |||
289 | 289 | | |
290 | 290 | | |
291 | 291 | | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
| 37 | + | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
| 41 | + | |
39 | 42 | | |
40 | 43 | | |
41 | 44 | | |
| |||
617 | 620 | | |
618 | 621 | | |
619 | 622 | | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
130 | 135 | | |
131 | 136 | | |
132 | 137 | | |
| |||
370 | 375 | | |
371 | 376 | | |
372 | 377 | | |
373 | | - | |
| 378 | + | |
| 379 | + | |
374 | 380 | | |
375 | 381 | | |
376 | 382 | | |
| |||
0 commit comments