Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ jobs:
node tests/console_api_contract_validation.mjs
node tests/console_binance_current_holdings_validation.mjs
node tests/console_api_worker_validation.mjs
node tests/decision_cockpit_api_validation.mjs
node tests/console_design_api_validation.mjs
node web/strategy-switch-console/frontend/node_modules/typescript/bin/tsc -p tests/tsconfig.console-gaps.json
node --experimental-strip-types tests/console_gap_contract_validation.mjs
Expand Down
75 changes: 75 additions & 0 deletions tests/console_api_contract_validation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,81 @@ validate("assets", { ...assetFixture, curve_status: "partial", curve_coverage: {
validate("assets", { ...assetFixture, curve_coverage: null });
assert.throws(() => validate("assets", { ...assetFixture, curve_status: "healthy" }), /curve_status: enum/);
assert.throws(() => validate("assets", { ...assetFixture, curve_coverage: { forward_filled_points: "1" } }), /curve_coverage: anyOf/);
// The decision cockpit read and action envelopes are published schema contracts.
const reviewEnvelope = {
schema_version: "qsl.decision_review.v1",
server_time: "2026-10-15T12:00:00Z",
data_status: "ready",
decision_id: "owner_decision:synthetic",
decision: {},
current_eligibility: { eligible: true, material_matches: true, expired: false, blocked: false, reason_codes: [] },
decision_authority: null,
decision_receipt: null,
operation: null,
policy: {},
errors: [],
};
validate("decision_review", reviewEnvelope);
const { server_time: _reviewTime, ...reviewWithoutTime } = reviewEnvelope;
assert.throws(() => validate("decision_review", reviewWithoutTime), /server_time: required/);
assert.throws(
() => validate("decision_review", { ...reviewEnvelope, current_eligibility: { eligible: "yes" } }),
/current_eligibility\.material_matches: required/,
);
// Tier-policy parameters are published as declarative owner intent only.
const tierPolicyEnvelope = {
schema_version: "qsl.risk_tier_policy.v1",
tier: "CAPITAL_PRESERVATION",
policy_id: "capital_preservation_v1",
profile_id: "capital_preservation_v1",
composer_mdd_multiple: 1,
promotion_size_scale: 0.5,
executable: false,
activation_status: "not_connected",
owner_intent_only: true,
no_order: true,
execution_authority_granted: false,
};
validate("risk_tier_policy", tierPolicyEnvelope);
validate("decision_review", { ...reviewEnvelope, tier_policies: [tierPolicyEnvelope] });
assert.throws(
() => validate("risk_tier_policy", { ...tierPolicyEnvelope, composer_mdd_multiple: "1.0" }),
/composer_mdd_multiple: type/,
);
assert.throws(
() => validate("risk_tier_policy", { ...tierPolicyEnvelope, tier: "UNKNOWN_TIER" }),
/tier: enum/,
);
assert.throws(
() => validate("risk_tier_policy", { ...tierPolicyEnvelope, executable: true }),
/executable/,
);
assert.throws(
() => validate("risk_tier_policy", { ...tierPolicyEnvelope, execution_authority_granted: true }),
/execution_authority_granted/,
);
const actionEnvelope = {
schema_version: "qsl.decision_action_result.v1",
server_time: "2026-10-15T12:00:00Z",
ok: true,
replayed: false,
decision_id: "owner_decision:synthetic",
revision: "rev1-0123456789abcdef",
action: "keep_parked",
operation_id: "synthetic-operation",
operation_sha256: "a".repeat(64),
decision_receipt: null,
decided_at: null,
decision_state: {},
operation: null,
policy: {},
};
validate("decision_action_result", actionEnvelope);
assert.throws(() => validate("decision_action_result", { ...actionEnvelope, revision: "r1" }), /decision_action_result\.revision/);
assert.throws(
() => validate("decision_action_result", { ...actionEnvelope, schema_version: "qsl.decision_action_result.v2" }),
/schema_version/,
);
const endpoints = {
"/api/decisions-inbox": "inbox",
"/api/owner-decisions/history": "decision_history",
Expand Down
20 changes: 16 additions & 4 deletions tests/console_api_worker_validation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const require = createRequire(
new URL("../web/strategy-switch-console/package.json", import.meta.url),
);
const { Miniflare } = require("miniflare");
// Decision inbox payloads carry a per-request server_time; compare them without it.
const withoutServerTime = ({ server_time: _serverTime, ...rest }) => rest;
const account = {
key: "synthetic-alpha",
label: "Synthetic alpha",
Expand Down Expand Up @@ -239,7 +241,11 @@ try {
assert.deepEqual(combined.body.accounts, accounts.body, "combined accounts retain the existing body");
validate("accounts", combined.body.accounts);
validate("inbox", combined.body.inbox);
assert.deepEqual(combined.body.inbox, (await call("/api/decisions-inbox", { cookie: reader })).body);
assert.deepEqual(
withoutServerTime(combined.body.inbox),
withoutServerTime((await call("/api/decisions-inbox", { cookie: reader })).body),
"combined inbox matches the standalone inbox body apart from server_time",
);
assert.equal((await call("/api/accounts?include=decisions-inbox", { cookie: null })).status, 401);
assert.equal((await call("/api/accounts?include=decisions-inbox", { method: "POST", body: {} })).status, 405);
for (const query of ["include=", "include=other", "include=decisions-inbox&include=decisions-inbox",
Expand Down Expand Up @@ -383,7 +389,10 @@ try {
resetCounts();
const result = await read("/api/accounts?include=decisions-inbox");
assert.equal(result.status, 200);
assert.deepEqual(result.body, { accounts: oldAccounts.body, inbox: oldInbox.body });
assert.deepEqual(
{ accounts: result.body.accounts, inbox: withoutServerTime(result.body.inbox) },
{ accounts: oldAccounts.body, inbox: withoutServerTime(oldInbox.body) },
);
assert.deepEqual(counts, { metadata: 1, owner: 1, promotion: 1, recovery: 1, credential: 1, outbound: 0 });
generation = 7;
assert.equal((await read("/api/accounts?include=decisions-inbox")).body.accounts.accounts[0].pending_draft_count, 7,
Expand Down Expand Up @@ -422,8 +431,11 @@ try {
credentialForbidden = true;
const forbiddenSource = await read("/api/accounts?include=decisions-inbox");
assert.equal(forbiddenSource.body.inbox.status, "read_failed");
assert.deepEqual(forbiddenSource.body.inbox, (await read("/api/decisions-inbox")).body,
"a nested source 403 retains the original inbox classification");
assert.deepEqual(
withoutServerTime(forbiddenSource.body.inbox),
withoutServerTime((await read("/api/decisions-inbox")).body),
"a nested source 403 retains the original inbox classification",
);
credentialForbidden = false;
const beforeDenied = { ...counts };
assert.equal((await read("/api/accounts?include=decisions-inbox", {
Expand Down
11 changes: 11 additions & 0 deletions tests/console_evidence_metadata_validation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,17 @@ assert.equal(JSON.stringify(queue).includes("never-public"), false);
assert.equal(fixture.commands.filter(command => command?.action === "promotion_read").length, 1, "the existing authority observation is reused exactly once");
assert.equal(fixture.reads.filter(name => name === `research_promotion_ticket:${ticket.ticket_id}`).length, 1);
assert.equal(fixture.writes(), 0);
const materialKey = "a".repeat(64);
const expiresAt = "2026-11-02T00:00:00Z";
const authorityFixture = readFixture({ migrated: true, eligible: true, blocked: false, material_key: materialKey, expires_at: expiresAt, decision: null });
const authorityQueue = await (await queueRead(authorityFixture, "synthetic-reader")).json();
assert.deepEqual(authorityQueue.tickets[0].decision_authority, {
material_sha256: materialKey, expires_at: expiresAt, eligible: true, blocked: false,
unavailable: false, source: "durable_human_decision_material",
}, "the public authority view retains the original durable observation");
assert.deepEqual(authorityQueue.applications[0].decision_authority, authorityQueue.tickets[0].decision_authority);
assert.equal(authorityFixture.commands.filter(command => command?.action === "promotion_read").length, 1);
assert.equal(authorityFixture.writes(), 0);
for (const login of [null, "synthetic-denied"]) {
const denied = readFixture({ migrated: true, eligible: true, blocked: false });
assert.equal((await queueRead(denied, login)).status, 401);
Expand Down
Loading
Loading