Skip to content

Commit a31ae8a

Browse files
committed
fix(verify, plugin-dev, plugin-hono-server): runtime strings state each decision in words instead of a tracker number (stage 4)
The verify RLS runner's report, persona provisioning errors and probe metadata, the verify harness's organizations remedy, the dev plugin's tenancy refusals and no-auth warning, and the Hono server's no-API warning pointed at tracker numbers. The numbers go; where a sentence leaned on one, it now says the decision in words. Two pins that asserted a number now assert the decision sentence. The prose-id ledger is recomputed with --census-ledger: the four rows leave, nothing else moves. Claude-Session: https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7c5a311 commit a31ae8a

7 files changed

Lines changed: 16 additions & 30 deletions

File tree

‎packages/plugins/plugin-dev/src/dev-plugin-optional-load-failure.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ describe('DevPlugin — an optional service that is installed and fails to const
280280
const line = allLines(ctx).find((l) => l.includes('REST API NOT enabled'));
281281
expect(line, 'the no-auth refusal is reported on its own terms').toBeDefined();
282282
expect(line).toContain('no auth is mounted');
283-
expect(line).toContain('#3963');
283+
expect(line).toContain('always denied, with no setting that turns that off');
284284
expect(line).toContain('NOT a missing-package problem');
285285
// And the false claim it used to emit instead is gone.
286286
expect(allLines(ctx).some((l) => l.includes('@objectstack/rest not installed'))).toBe(false);

‎packages/plugins/plugin-dev/src/dev-plugin.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ export class DevPlugin implements Plugin {
871871
+ (mountCode !== undefined ? `code: ${String(mountCode)} — ` : '')
872872
+ `${mountMessage}. OS_ALLOW_DEGRADED_TENANCY does NOT apply to this failure and will `
873873
+ 'not get past it: it covers an ABSENT multi-org runtime the operator accepts doing '
874-
+ 'without, not a present one that declined. (#4818)',
874+
+ 'without, not a present one that declined.',
875875
);
876876
}
877877
ctx.logger.info(` ✔ Organizations plugin enabled (posture '${tenancyPosture}': organization_id auto-stamp, per-org seed)`);
@@ -931,7 +931,8 @@ export class DevPlugin implements Plugin {
931931
if (!authMounted) {
932932
ctx.logger.warn(
933933
' ✘ REST API NOT enabled: no auth is mounted in this stack, so no caller could ever '
934-
+ 'authenticate and anonymous access to object data is always denied (#3963). This is NOT a '
934+
+ 'authenticate and anonymous access to object data is always denied, with no setting that '
935+
+ 'turns that off. This is NOT a '
935936
+ 'missing-package problem — @objectstack/rest was never consulted. Install/enable '
936937
+ 'plugin-auth (or the `auth` tier), or drop the REST API from this dev stack.',
937938
);
@@ -997,7 +998,7 @@ export class DevPlugin implements Plugin {
997998
+ 'requested multi-organization isolation must not serve traffic without it (ADR-0093 D5). '
998999
+ 'The plugin reported (verbatim — the framework does not interpret it): '
9991000
+ `${err?.message ?? String(err)}. OS_ALLOW_DEGRADED_TENANCY does NOT apply: it covers an `
1000-
+ 'ABSENT multi-org runtime, not a present one that declined. (#4818)',
1001+
+ 'ABSENT multi-org runtime, not a present one that declined.',
10011002
);
10021003
}
10031004
ctx.logger.error(`Failed to init child plugin ${plugin.name}: ${err.message}`);

‎packages/plugins/plugin-hono-server/src/hono-plugin.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ export class HonoServerPlugin implements Plugin {
680680
if (!hasPlugin(REST_API_PLUGIN) && !hasPlugin(RUNTIME_DISPATCHER_PLUGIN)) {
681681
ctx.logger.warn(
682682
'No data or discovery API is mounted on this server. HonoServerPlugin is a '
683-
+ 'transport adapter and serves neither (#4073). Mount `createRestApiPlugin` '
683+
+ 'transport adapter and serves neither. Mount `createRestApiPlugin` '
684684
+ 'from @objectstack/rest for full CRUD behind the gate stack, or '
685685
+ '`createDispatcherPlugin` from @objectstack/runtime.',
686686
);

‎packages/plugins/plugin-hono-server/src/hono-transport-only.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ describe('#4073 end state — the plugin serves transport and /me/* only', () =>
8989
// The message must carry the remedy, not just the diagnosis.
9090
expect(hit[0]).toContain('@objectstack/rest');
9191
expect(hit[0]).toContain('@objectstack/runtime');
92-
expect(hit[0]).toContain('#4073');
92+
expect(hit[0]).toContain('transport adapter and serves neither');
9393
});
9494

9595
it('a REST-composed boot stays quiet', async () => {

‎packages/verify/src/harness.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ export async function bootStack(
623623
'authority on what it has to publish.'
624624
: `Install/link it in THIS APP (${hostRoot}) — and DECLARE it in that app's ` +
625625
'package.json, which is what is actually checked: a package merely reachable through ' +
626-
'NODE_PATH or a hoisted workspace store is not accepted (#4719) — to run multi-org fixtures.';
626+
'NODE_PATH or a hoisted workspace store is not accepted — to run multi-org fixtures.';
627627
throw new Error(
628628
'verify: multiTenant=true requires the enterprise @objectstack/organizations package (migrated from plugin-org-scoping, ADR-0105 D12). ' +
629629
`${remedy} (${(e as Error).message})`,

‎packages/verify/src/rls.ts‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ export function rlsProbePermissionSet(config: any): PermissionSet {
354354
label: `RLS probe scope for ${o.name}`,
355355
description:
356356
'Verifier-authored owner narrowing (select only) — puts the probe persona outside the ' +
357-
'scope of every record it did not create, so the by-id-write class is reachable (#7685).',
357+
'scope of every record it did not create, so the by-id-write class is reachable.',
358358
object: o.name,
359359
operation: 'select',
360360
using: 'created_by == current_user.id',
@@ -428,7 +428,7 @@ export async function provisionRlsProbePersona(
428428
throw new Error(
429429
'verify: cannot provision the RLS probe persona — no ObjectQL engine on this stack. ' +
430430
'The probe needs object-level read+edit grants, without which every by-id probe is ' +
431-
'masked by the object gate and the #1994 class is unreachable (#7685).',
431+
'masked by the object gate and a by-id write that bypasses RLS is unreachable.',
432432
);
433433
}
434434
const sysCtx = { context: { isSystem: true } };
@@ -461,7 +461,7 @@ export async function provisionRlsProbePersona(
461461
description:
462462
'Ephemeral persona minted by `objectstack verify --rls`: object-level read+edit on every ' +
463463
'declared object plus an owner-scoped SELECT narrowing, so a by-id refusal is attributable ' +
464-
'to the record gate rather than the object gate (#7685).',
464+
'to the record gate rather than the object gate.',
465465
object_permissions: JSON.stringify(probeSet.objects ?? {}),
466466
field_permissions: '{}',
467467
system_permissions: '[]',
@@ -550,7 +550,7 @@ export async function provisionRlsPositionPersona(
550550
throw new Error(
551551
`verify: cannot provision the RLS position persona for '${position}' — no ObjectQL engine on ` +
552552
'this stack. Without the position assignment the app\'s position-gated policies are not ' +
553-
'applicable to the persona, so the app-authored narrowing is unreachable (#7978).',
553+
'applicable to the persona, so the app-authored narrowing is unreachable.',
554554
);
555555
}
556556
const sysCtx = { context: { isSystem: true } };
@@ -572,7 +572,7 @@ export async function provisionRlsPositionPersona(
572572
business_unit_id: null,
573573
organization_id: null,
574574
granted_by: null,
575-
reason: `Ephemeral persona minted by \`objectstack verify --rls\`: holds '${position}' and nothing else, so the app's own position-gated RLS narrowing is exercised (#7978).`,
575+
reason: `Ephemeral persona minted by \`objectstack verify --rls\`: holds '${position}' and nothing else, so the app's own position-gated RLS narrowing is exercised.`,
576576
},
577577
sysCtx,
578578
);
@@ -765,7 +765,7 @@ async function probeAsPersona(
765765
object,
766766
status: 'rls-hole',
767767
target: origin,
768-
detail: `the probe cannot read it (GET ${bRead.status}) yet MUTATED it by id (PATCH ${bWrite.status}) — by-id write bypassed RLS (#1994 class)${via}`,
768+
detail: `the probe cannot read it (GET ${bRead.status}) yet MUTATED it by id (PATCH ${bWrite.status}) — by-id write bypassed RLS, and a caller that cannot read a record must not be able to write it${via}`,
769769
});
770770
} else {
771771
results.push({
@@ -905,7 +905,7 @@ function summaryLine(s: RlsSummary): string {
905905
}
906906

907907
export function formatRlsReport(report: RlsReport): string {
908-
const lines: string[] = [`\n=== objectstack verify (RLS / #1994) — ${report.app} ===`];
908+
const lines: string[] = [`\n=== objectstack verify (RLS / cross-owner by-id-write invariant) — ${report.app} ===`];
909909
for (const r of report.results) {
910910
lines.push(` ${statusMark(r.status)} ${r.object} [${r.status}] ${r.detail ?? ''}`);
911911
}
@@ -940,7 +940,7 @@ export function formatRlsReport(report: RlsReport): string {
940940
// would claim N× the reach the fan-out actually has.
941941
const cov = report.positionCoverage;
942942
lines.push(
943-
`\n ── position personas (#7978) — ${cov.ran.length} of ${cov.declared.length} declared position(s) probed`,
943+
`\n ── position personas (each holds one declared position and nothing else) — ${cov.ran.length} of ${cov.declared.length} declared position(s) probed`,
944944
);
945945
if (cov.note) lines.push(` · ${cov.note}`);
946946
for (const run of report.positionRuns) {

‎scripts/doc-authoring-prose-id.baseline.json‎

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,6 @@
176176
"packages/plugins/plugin-audit/src/translations/zh-CN.objects.generated.ts": {
177177
"#11507": 1
178178
},
179-
"packages/plugins/plugin-dev/src/dev-plugin.ts": {
180-
"#3963": 1,
181-
"#4818": 2
182-
},
183179
"packages/plugins/plugin-email/src/email-service.ts": {
184180
"#5172": 1
185181
},
@@ -189,9 +185,6 @@
189185
"packages/plugins/plugin-email/src/templates/auth-templates.ts": {
190186
"#8019": 4
191187
},
192-
"packages/plugins/plugin-hono-server/src/hono-plugin.ts": {
193-
"#4073": 1
194-
},
195188
"packages/plugins/plugin-security/src/bootstrap-system-capabilities.ts": {
196189
"#5876": 1,
197190
"#8552": 2
@@ -483,13 +476,5 @@
483476
},
484477
"packages/triggers/trigger-record-change/src/record-change-trigger.ts": {
485478
"#3457": 1
486-
},
487-
"packages/verify/src/harness.ts": {
488-
"#4719": 1
489-
},
490-
"packages/verify/src/rls.ts": {
491-
"#1994": 3,
492-
"#7685": 3,
493-
"#7978": 3
494479
}
495480
}

0 commit comments

Comments
 (0)