mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-19 09:45:07 +00:00
fix+test+docs: D53 — tried_providers schema semantic fix (D45 P2 deferral closed) (#30)
Sixth Phase 3 D-day. Small focused fix for the D45 fresh-context opus
reviewer P2 finding that was deferred: auditCtx.tried_providers on the
key_no_provider_access 403 path was being stamped with the ORIGINAL
chain (which was filtered out, never dispatched), distorting downstream
audit queries like "which providers did key X actually call".
CHANGES:
- server.mjs handleChatCompletions ~L815: on key_no_provider_access
403, auditCtx.tried_providers = [] (was _originalChainProviders).
The configured-but-blocked chain still appears in the human-
readable error message body — the audit just doesn't claim those
providers were "tried" when the server's filter dispatched zero.
- docs/adr/0007-multi-key-auth.md § 8 amendment: new paragraph
spelling out the tried_providers semantic. "The list of providers
the server actually dispatched a spawn against. A provider that
was configured in the chain but filtered out by providers_enabled
gating is NOT included — the key didn't try the provider, the
gate did. On the 403 path tried_providers is the empty array."
Plus a forward note that audit log rotation moved to Phase 3 /
ADR 0008 § 5.
- test-features.mjs Suite 20h-extra-audit (+1 test — 600 → 601):
creates guest key with providers_enabled: ['mistral']; fires
request for Anthropic-routed model; asserts 403
key_no_provider_access; reads audit row from audit.ndjson;
asserts tried_providers === []. Pins the D53 semantic against
regression.
- CHANGELOG.md: D53 entry under Unreleased.
NOT IN D53:
- E2E + docs polish (D54)
- Phase 3 close → v0.3.0 (D55; maintainer-triggered)
Test count: 600 → 601 (+1). Verified locally via npm test.
AUTHORITY:
- ADR 0007 § 8 amendment (D53, 2026-05-25).
- D45 fresh-context opus reviewer P2 deferral note.
- CLAUDE.md release_kit overlay phase_rolling_mode — under Unreleased.
- Standing autopilot grant.
ALIGNMENT.md scope check: small entry-surface change (audit context
field assignment on one error path) + ADR amendment + new test. Per
ALIGNMENT.md Rule 1 the ADR amendment is the authority citation for
the server change. No provider plugin / IR / models-registry change.
Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -10146,6 +10146,35 @@ describe('Suite 20 — server.mjs auth integration (D45, ADR 0007)', () => {
|
||||
});
|
||||
assert.equal(r.status, 200);
|
||||
});
|
||||
|
||||
it('20h-extra-audit: D53 — key_no_provider_access 403 audit row has tried_providers = []', async () => {
|
||||
// Per ADR 0007 § 8 tried_providers semantics clarification: the field
|
||||
// captures providers the server actually dispatched. On 403 (filter
|
||||
// rejected the whole chain) the server dispatched zero providers, so
|
||||
// tried_providers MUST be []. The configured-but-blocked chain only
|
||||
// appears in the human-readable error message, not in the audit.
|
||||
// D45 P2 deferral fix — was previously stamping the original chain
|
||||
// which distorted "which providers did key X actually call" queries.
|
||||
const { id, plaintext_token } = createKey({ name: '20h-extra-audit', owner_tier: 'guest', providers_enabled: ['mistral'], olpHome: TMP });
|
||||
const r = await fetch({
|
||||
port, method: 'POST', path: '/v1/chat/completions',
|
||||
headers: { Authorization: `Bearer ${plaintext_token}` },
|
||||
body: { model: 'claude-sonnet-4-6', messages: [{ role: 'user', content: '20h-extra-audit' }] },
|
||||
});
|
||||
assert.equal(r.status, 403);
|
||||
assert.equal(JSON.parse(r.body).error.type, 'key_no_provider_access');
|
||||
// Wait for the res.on('finish') audit append
|
||||
await new Promise(resolve => setTimeout(resolve, 25));
|
||||
const auditPath = _pathJoinForSetup(TMP, 'logs', 'audit.ndjson');
|
||||
const lines = fsReadFileSync(auditPath, 'utf-8').trim().split('\n').filter(Boolean);
|
||||
const row = lines.map(l => JSON.parse(l)).find(r =>
|
||||
r.path === '/v1/chat/completions' && r.status_code === 403 && r.key_id === id,
|
||||
);
|
||||
assert.ok(row, '403 audit row must be present');
|
||||
assert.equal(row.error_code, 'key_no_provider_access');
|
||||
assert.deepEqual(row.tried_providers, [],
|
||||
'tried_providers MUST be [] on key_no_provider_access — D53 semantic fix per ADR 0007 § 8 clarification');
|
||||
});
|
||||
});
|
||||
|
||||
// ── 20i: per-key cache namespace isolation (criterion #1) ────────────────
|
||||
|
||||
Reference in New Issue
Block a user