Measured by #7616's dev on main @ 098b629 while adding a method to this contract (report, section "Two things that came out differently than the brief assumed"). Deliberately not folded into PR #7829 — correctly, since it is an unrelated ledger edit inside a contract addition. Filed unassigned.
The gap
packages/spec/src/contracts/security-service.test.ts is the contract test for ISecurityService, and its job is to be the exhaustive gate on that surface — the thing that notices when the interface grows a member nobody implemented.
Three members — hasWriteBypass, resolveWriteScope, describeDelegableScope — are required on ISecurityService and appear in neither the test's assertion list nor its makeService() literal.
That mismatch does not go red, because it is being held open by a suppression: the file carries exactly 1 entry in test-typecheck-debt.json — TS2322 at line 21, "type … is not assignable to type ISecurityService". The compile-time half of the contract test is being asserted past a suppressed error.
Why this is worth a card rather than a line in a PR
A gate that is itself type-suppressed does not gate. Any future required member can be added to ISecurityService with no test noticing — which is the exact drift class #7616 was filed to stop, one level up: #7616 is about one rule with three copies; this is about the check that would catch the next such rule failing silently.
It also means a reader who consults this test to learn the contract's surface gets an incomplete answer, with nothing signalling the omission.
Fix shape
Complete makeService()'s literal (and the assertion list) with the three missing methods so the file type-checks without suppression.
⛔ The ratchet direction is 1 → 0, not upward. Under the exact ratchet, taking the entry to zero means deleting it from test-typecheck-debt.json — a legitimate shrink. Do not raise the ledger, and do not widen the suppression to cover a new member instead.
Note for whoever takes it
This belongs to whoever owns hasWriteBypass / resolveWriteScope / describeDelegableScope — completing a stub for three methods means asserting what their contract-correct shapes are, which is a judgement about those methods, not about the test file.
Confirm the measurement on current main before acting: the entry count and line number are from 098b629, and packages/spec's exact ratchet was measured at 265 errors / 57 files at that commit. If PR #7829 (which adds an optional method to this same interface) has merged by then, re-read — an optional member changes neither the runtime assertion nor the error count, but the line number may shift.
Related
Measured by #7616's dev on
main@098b629while adding a method to this contract (report, section "Two things that came out differently than the brief assumed"). Deliberately not folded into PR #7829 — correctly, since it is an unrelated ledger edit inside a contract addition. Filed unassigned.The gap
packages/spec/src/contracts/security-service.test.tsis the contract test forISecurityService, and its job is to be the exhaustive gate on that surface — the thing that notices when the interface grows a member nobody implemented.Three members —
hasWriteBypass,resolveWriteScope,describeDelegableScope— are required onISecurityServiceand appear in neither the test's assertion list nor itsmakeService()literal.That mismatch does not go red, because it is being held open by a suppression: the file carries exactly 1 entry in
test-typecheck-debt.json—TS2322at line 21, "type … is not assignable to typeISecurityService". The compile-time half of the contract test is being asserted past a suppressed error.Why this is worth a card rather than a line in a PR
A gate that is itself type-suppressed does not gate. Any future required member can be added to
ISecurityServicewith no test noticing — which is the exact drift class #7616 was filed to stop, one level up: #7616 is about one rule with three copies; this is about the check that would catch the next such rule failing silently.It also means a reader who consults this test to learn the contract's surface gets an incomplete answer, with nothing signalling the omission.
Fix shape
Complete
makeService()'s literal (and the assertion list) with the three missing methods so the file type-checks without suppression.⛔ The ratchet direction is 1 → 0, not upward. Under the exact ratchet, taking the entry to zero means deleting it from
test-typecheck-debt.json— a legitimate shrink. Do not raise the ledger, and do not widen the suppression to cover a new member instead.Note for whoever takes it
This belongs to whoever owns
hasWriteBypass/resolveWriteScope/describeDelegableScope— completing a stub for three methods means asserting what their contract-correct shapes are, which is a judgement about those methods, not about the test file.Confirm the measurement on current
mainbefore acting: the entry count and line number are from098b629, andpackages/spec's exact ratchet was measured at 265 errors / 57 files at that commit. If PR #7829 (which adds an optional method to this same interface) has merged by then, re-read — an optional member changes neither the runtime assertion nor the error count, but the line number may shift.Related
/auth/me/permissionsand/me/appsre-implement permission-set resolution instead of calling the plugin's service — the copy that produced #7608 (and #7270, #7560) #7616 / PR feat(spec,plugin-security): publish the caller's resolved permission SETS on the security service (#7616) #7829 — where this was measured; addsresolvePermissionSetsForContext?to the same interface.getMetadataReadableFields?) and On objects that carry sharing rules, sharing middleware answers FORBIDDEN before RLS update-wideners are consulted — the identical widener works on rule-less objects #5493 (checkAuthoredRowWrite?) — the optional-member precedent on this file, both of which the assertion list does cover.