Repository navigation
Commit ba57588
fix(service-settings): the settings audit trail records secret-valued settings with the keyed digest (#21809)
Fixes #21792
Clause-②: no
## What changes
The settings audit trail now records secret-valued settings (encrypted
keys) with the platform's keyed digest (`ICryptoProvider.keyedDigest`),
never the unkeyed `digest`. This follows the maintainer ruling recorded
on the card. Non-secret settings are unchanged.
- **`packages/services/service-settings/src/settings-service.ts`**: one
private helper, `secretAuditDigest`, supplies the fingerprint for a
secret-valued write on both write branches (the `sys_secret` path and
the legacy inline-adapter path). Both ledgers take it: the
`sys_audit_log` `config_change` row (`valueDigest`, now spelled with an
`hmac-sha256:` digest inside the existing encrypted marker) and the
`sys_setting_audit` row (`newHash`).
- **No keyed digest available.** This happens when no crypto provider is
wired (a host that builds the service with only a `CryptoAdapter`) or
when the provider refuses. The rows then record the write with no
fingerprint: `valueDigest` is the bare encrypted marker and `newHash` is
null. A `warn` is logged once per key. The write itself is never
refused, matching the existing rule that a ledger never fails a settings
save. The unkeyed digest is never used as a fallback.
- **`packages/spec/src/contracts/crypto-provider.ts`**: the contract
text is revised as the ruling asks. `digest` is the audit fingerprint of
non-secret values only. `keyedDigest` requirement 3 now says a secret's
audit fingerprint comes from it and never from `digest`, and that with
no keyed digest the trail records none. Comment-only: no type, export or
schema change.
- **Changeset**: `@objectstack/service-settings` patch and
`@objectstack/spec` patch (the doc text ships in the `.d.ts`).
## Consumers that compare these digests
No non-test code reads or compares `valueDigest` / `new_hash` /
`old_hash`: `git grep` over `packages/**` returned only the writers, the
object definition and comments. Equal-value detection still works for a
reader, because the keyed digest is stable for equal input under one
key. Three existing tests pinned the old unkeyed spelling for a secret.
They were updated, not deleted: two now expect the keyed shape, and one
(the legacy adapter, no provider) now expects no fingerprint.
## Tests (at `f34f69594c`; test code is unchanged since `fc5c86e1c6`)
- New `settings-audit-secret-digest.test.ts` (7 cases). For a secret,
both ledgers carry `provider.keyedDigest(value)`, which is neither
`provider.digest(value)` nor the plain SHA-256 of the value. The
fingerprint is stable for equal values and distinct for different ones.
A reset records null. The legacy branch with a provider records the
keyed digest. The legacy branch with no provider records no fingerprint,
warns once, and the write still lands. A provider that refuses still
lets the write land. For a non-secret value, both ledgers keep the
adapter digest of the canonical JSON, unchanged.
- `pnpm --filter @objectstack/service-settings test`: 34 files, 612
tests passed. `typecheck` (`tsc --noEmit`, `include: ["src"]`, so it
covers the tests) passed.
- **Ablation, two legs, done with `scripts/ablation-replace.mjs`**. The
tests import `src`, so no dist rebuild was involved. Leg 1 put back the
unkeyed `digest` on the `sys_secret` branch: 2 of 7 failed (the
keyed-digest case and the refusing-provider case). Leg 2 put back the
adapter digest on the legacy branch: 2 of 7 failed (both legacy cases).
Each leg restored to the HEAD blob (`a148f503e350`) with `git diff HEAD`
empty.
- **Derived gate families** (`dispatch-gates.mjs --commands`, 87): 85
exit 0. `check:dual-build-cjs-loads` exited 3 (PREREQUISITE NOT MET: it
needs a whole-repo build). `check:type-check-debt` was killed twice by
the foreground cap. Both are NOT MEASURED and left to CI. `--ran`
reconciliation: 87 accounted, 0 unrun.
- **Lint, narrowed to the 5 touched `.ts` files**: `eslint
--no-inline-config --format json` reported 5 files, 0 errors, 0
warnings. The config's TS block matches `**/*.{ts,…}`, and type-aware
linting is not enabled (no `parserOptions.project`), so this diff cannot
change any verdict on an untouched file.
## Acceptance notes
- **Optional `oldHash` (not done).** The `sys_setting_audit` writer
still hard-codes `oldHash: null`. Recording the previous fingerprint of
a secret would mean decrypting the prior ciphertext on every write, so
it is not the small rider the dispatch allowed. It is left for a
follow-up.
- The `sys_setting_audit` object's `old_hash` / `new_hash` field
descriptions in `platform-objects` still say "SHA-256 of the … value".
That was already inexact for the default adapter, and it is outside this
card's file surface. Carrier: none named.
- Audit rows written before this release keep their old fingerprint.
Rotating the data key changes every later secret fingerprint.
---
_Generated by [Claude
Code](https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 18c7dfd commit ba57588
7 files changed
Lines changed: 301 additions & 21 deletions
File tree
- .changeset
- packages
- services/service-settings/src
- spec/src/contracts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
Lines changed: 192 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
Lines changed: 5 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
184 | 184 | | |
185 | 185 | | |
186 | 186 | | |
187 | | - | |
| 187 | + | |
188 | 188 | | |
189 | 189 | | |
190 | 190 | | |
| |||
203 | 203 | | |
204 | 204 | | |
205 | 205 | | |
206 | | - | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
207 | 209 | | |
208 | 210 | | |
209 | 211 | | |
| |||
2005 | 2007 | | |
2006 | 2008 | | |
2007 | 2009 | | |
2008 | | - | |
| 2010 | + | |
2009 | 2011 | | |
2010 | 2012 | | |
2011 | 2013 | | |
| |||
Lines changed: 65 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
554 | 554 | | |
555 | 555 | | |
556 | 556 | | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
557 | 562 | | |
558 | 563 | | |
559 | 564 | | |
| |||
1575 | 1580 | | |
1576 | 1581 | | |
1577 | 1582 | | |
| 1583 | + | |
| 1584 | + | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | |
| 1600 | + | |
| 1601 | + | |
| 1602 | + | |
| 1603 | + | |
| 1604 | + | |
| 1605 | + | |
| 1606 | + | |
| 1607 | + | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
| 1614 | + | |
| 1615 | + | |
| 1616 | + | |
| 1617 | + | |
| 1618 | + | |
| 1619 | + | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
1578 | 1632 | | |
1579 | 1633 | | |
1580 | 1634 | | |
| |||
1669 | 1723 | | |
1670 | 1724 | | |
1671 | 1725 | | |
1672 | | - | |
| 1726 | + | |
| 1727 | + | |
| 1728 | + | |
1673 | 1729 | | |
1674 | 1730 | | |
1675 | 1731 | | |
| |||
1696 | 1752 | | |
1697 | 1753 | | |
1698 | 1754 | | |
1699 | | - | |
| 1755 | + | |
1700 | 1756 | | |
1701 | 1757 | | |
1702 | 1758 | | |
| |||
1706 | 1762 | | |
1707 | 1763 | | |
1708 | 1764 | | |
1709 | | - | |
| 1765 | + | |
| 1766 | + | |
| 1767 | + | |
1710 | 1768 | | |
1711 | 1769 | | |
1712 | 1770 | | |
| |||
1750 | 1808 | | |
1751 | 1809 | | |
1752 | 1810 | | |
1753 | | - | |
| 1811 | + | |
| 1812 | + | |
| 1813 | + | |
1754 | 1814 | | |
1755 | 1815 | | |
1756 | 1816 | | |
| |||
2431 | 2491 | | |
2432 | 2492 | | |
2433 | 2493 | | |
2434 | | - | |
| 2494 | + | |
2435 | 2495 | | |
2436 | 2496 | | |
2437 | 2497 | | |
| |||
Lines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
445 | 445 | | |
446 | 446 | | |
447 | 447 | | |
448 | | - | |
| 448 | + | |
| 449 | + | |
449 | 450 | | |
450 | | - | |
| 451 | + | |
451 | 452 | | |
452 | 453 | | |
453 | 454 | | |
| |||
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
39 | | - | |
| 39 | + | |
| 40 | + | |
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
| |||
0 commit comments