Repository navigation
Commit 412d7dd
docs(qa): checklist items for the 17.7 pre-release security fixes (#21943)
Part of #21932
Clause-②: no
## What changes
The platform checklist gains items for the rules the 17.7 pre-release
security follow-up landed, and two re-checks from the card are resolved.
All edits are in `docs/qa/platform-checklist/areas/*.json`.
`automation.json` is untouched (open PR #21928 holds it).
| Card row | Disposition | Item |
|---|---|---|
| #21792 (PR #21809) settings audit and secret-valued settings | new
item | `platform-core.settings-audit-secret-fingerprint` |
| #21846 (PR #21872) implicit account linking | new item |
`identity-auth.implicit-account-linking-ownership` |
| #21839 (PR #21890) share-link password | three clauses added, rev 4 to
5 | `access-security.share-link-capability-tokens` |
| #21836 (PR #21879) global search skips unreadable objects, plus the
two cases #21880 lists | new item |
`search.global-search-skips-unreadable` |
| re-check 1: A2 / A7 and the plugin-driver boundary | rev 2 to 3 |
`integration-system.datasource-credential-refusal-matrix` |
| re-check 2: the #21845 CLI and quorum N1 notes | already applied by
#21891, no edit | `cli.scaffold-first-run`,
`cli.scaffold-console-first-paint`, `approvals.quorum-m-of-n` |
Each item states rules, not reproductions. Withheld security detail
stays out.
### Grounding, per row
- **Settings audit fingerprint.** Both ledgers record the keyed digest
for a secret-valued setting, or no fingerprint when none is available,
and never the value or an unkeyed hash. Grounded in
`settings-service.ts#secretAuditDigest`,
`config-change-audit.ts#CONFIG_CHANGE_ACTION` and the contract text at
`crypto-provider.ts#keyedDigest`. The pin is
`settings-audit-secret-digest.test.ts` (7 cases). The offline check
carries a positive control: the non-secret key's unkeyed digest IS
found, so a no-hit on the secret rows means something. The
no-keyed-digest arm cannot be reached on a stock boot, so that clause is
scored from the pin.
- **Implicit account linking.** Four rules: no implicit link to an
unverified local user; an unlink is honoured; an explicit, signed-in
link still works and lifts the refusal; the platform IdP exception holds
only on its OAuth path. Grounded in `implicit-account-linking.ts`
(`decideImplicitLink`, `IMPLICIT_LINK_REFUSED`,
`PLATFORM_IDP_PROVIDER_ID`, `recordUnlinkTombstone`,
`refuseImplicitAccountLink`) and the published `sso.mdx` section. The
pin is `implicit-account-linking.test.ts`. The item reuses the local
OIDC provider recipe from `identity-auth.linked-accounts-social`. The
platform-IdP clause and the operator override are pin-scored, and
knownGaps says why.
- **Share-link password.** The stored hash leaves on no exit (mint,
list, redemption). The password is accepted from the `X-Share-Password`
header, the query form is still accepted, and the default CORS
allow-list carries the header. Both public routes answer `Cache-Control:
no-store` and `Vary: X-Share-Password` on every outcome, and the
authenticated routes do not. Grounded in
`share-link-service.ts#withoutPasswordHash`,
`share-link-routes.ts#SHARE_LINK_PUBLIC_RESPONSE_HEADERS`, the runtime
`share-links.ts#PUBLIC_RESPONSE_HEADERS` and
`adapter.ts#DEFAULT_CORS_ALLOW_HEADERS`. The pins are the `[#21839]`
blocks in `share-link-password.test.ts`,
`share-links-public-cache-headers.test.ts` and the hono-plugin CORS
case. Existing clause indices are unchanged.
- **Global search.** An unreadable object is never queried, named or
counted. An explicit `objects=` naming one answers exactly as a name
that matches no object. The object stays refused at its own door. Row
scope still narrows a searched object, and a term found only in a field
hidden from the caller yields no hit. Grounded in
`protocol.ts#searchAll` (the `canReadObject` pre-filter and the
`getQueryableFields` narrowing). The pins are the dogfood
`search-skip-unreadable.dogfood.test.ts` and the 12 unit cases in
`protocol.search-skip-unreadable.test.ts`. The two #21880 cases have no
end-to-end pin yet, and knownGaps says so. The open pinyin-companion
finding on #21880 is recorded as a knownGap with a flag-off instruction,
at class level only. The persona reuses the area recipe
`qa-contributor-bound-member`.
- **Datasource credential matrix.** A2 / A7 (`acceptance[1]` and
`acceptance[6]`) are recorded as a known environment gap. They need a
reachable credential-protected database of a shipped driver, which no
run has had. No recipe is claimed, because none is proven. A successful
publish alone may not score them, and the stored-credential half of A7
can be read as a partial reading. Separately, the unknown-driver clause,
step 7, its negative and the title now state the ruled boundary from
#21921 and the docs note #21927. For a plugin driver, only the fixed
spellings are redacted (the canonical keys, the former aliases and URL
credentials). A non-canonical key served as written is the boundary, not
a FAIL. Grounded in `common.zod.ts#CANONICAL_CREDENTIAL_KEYS` and
`datasource-credential-redaction.ts#redactableConfigKeys`.
### Re-check 2 evidence (no edit)
At the claim ref `9dce635337`:
- `cli.scaffold-first-run` (rev 3) step 0 and
`cli.scaffold-console-first-paint` (rev 3) step 0 both drop the trailing
`npm install` and warn against adding it. Their rev 3 history entries
cite #21845. No other `npm install` step remains in `cli.json`.
- `approvals.quorum-m-of-n` (rev 4) `negative[0]` requires a
NON-PRIVILEGED repeat actor and names the documented admin override
(#3424) as never a distinctness FAIL.
## Remaining on #21932 (held, not in this PR)
- The #21864 row (public-form withdrawal layering). Its PR is still
open.
- The #21928 row (run-state trigger record mask). That PR adds its own
item in `automation.json`.
#21932 remains open for these two rows.
## Validation (at `a72b827e43`)
- `pnpm check:platform-checklist`: exit 0. It reports 15 areas and 273
items (269 active, 2 planned). The baseline was 270. Symbol anchors
resolve 674 of 684 (baseline 657 of 667): all 17 new anchors resolve,
and the #16898 residual is unchanged at 10.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 13 commands, and all 13 exit 0.
`check:doc-formula-expressions` first exited 3 (PREREQUISITE NOT MET:
`@objectstack/formula` and `@objectstack/lint` were not built). After
building them it exited 0. `--ran` reconciliation: 13 derived, 13 run, 0
unrun.
- No package source changed, so there is no package build, test or
typecheck. No changeset: `docs/qa/**` publishes nothing.
## Acceptance notes
- Source citations name test cases and symbols, never line numbers,
because `check:platform-checklist` refuses a `file:line` pin.
- `content/docs/data-modeling/drivers.mdx` says a plugin driver's
`config` is "stored and served to administrators as written". The read
redactor still withholds the canonical spellings (`password`,
`authToken`), the former aliases and URL credentials for such a driver
(`redactableConfigKeys`). So the docs sentence is slightly broader than
the code, and the code is the more protective of the two. The checklist
follows the code. This is noted only, with no card. Carrier: none.
- A run of `search.global-search-skips-unreadable` picks the walled
object and the hidden-field value on the live boot, behind premise
guards. The item names likely candidates and does not assume them.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 13a22d0 commit 412d7dd
5 files changed
Lines changed: 376 additions & 15 deletions
File tree
- docs/qa/platform-checklist/areas
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1510 | 1510 | | |
1511 | 1511 | | |
1512 | 1512 | | |
1513 | | - | |
| 1513 | + | |
1514 | 1514 | | |
1515 | 1515 | | |
1516 | | - | |
| 1516 | + | |
1517 | 1517 | | |
1518 | 1518 | | |
1519 | 1519 | | |
| |||
1541 | 1541 | | |
1542 | 1542 | | |
1543 | 1543 | | |
1544 | | - | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
1545 | 1548 | | |
1546 | 1549 | | |
1547 | 1550 | | |
| |||
1579 | 1582 | | |
1580 | 1583 | | |
1581 | 1584 | | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | |
| 1600 | + | |
| 1601 | + | |
| 1602 | + | |
1582 | 1603 | | |
1583 | 1604 | | |
1584 | 1605 | | |
1585 | 1606 | | |
1586 | | - | |
| 1607 | + | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
1587 | 1611 | | |
1588 | 1612 | | |
1589 | 1613 | | |
| |||
1593 | 1617 | | |
1594 | 1618 | | |
1595 | 1619 | | |
1596 | | - | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
1597 | 1623 | | |
1598 | 1624 | | |
1599 | 1625 | | |
| |||
1604 | 1630 | | |
1605 | 1631 | | |
1606 | 1632 | | |
1607 | | - | |
| 1633 | + | |
| 1634 | + | |
| 1635 | + | |
| 1636 | + | |
| 1637 | + | |
| 1638 | + | |
| 1639 | + | |
| 1640 | + | |
1608 | 1641 | | |
1609 | 1642 | | |
1610 | 1643 | | |
| |||
1630 | 1663 | | |
1631 | 1664 | | |
1632 | 1665 | | |
| 1666 | + | |
| 1667 | + | |
| 1668 | + | |
| 1669 | + | |
| 1670 | + | |
| 1671 | + | |
1633 | 1672 | | |
1634 | 1673 | | |
1635 | 1674 | | |
| |||
0 commit comments