gateway-scooling-write-back-smoke.test.mjs
200 lines 6.4 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 1 day ago
1 import { describe, it } from 'node:test';
2 import assert from 'node:assert/strict';
3 import http from 'node:http';
4 import express from 'express';
5
6 import {
7 createScoolingWriteBackSmokeRouter,
8 validSmokeRequest,
9 } from '../hub/gateway/scooling-write-back-smoke.mjs';
10
11 function validPayload() {
12 return {
13 requestId: 'request-scooling-smoke-001',
14 targetId: 'phase-2-hosted-knowtation-staging',
15 kind: 'hosted_knowtation',
16 environment: 'staging',
17 vaultId: 'staging-vault-fixture',
18 actions: [
19 'metadata_read',
20 'proposal_dry_run',
21 'conflict_check_dry_run',
22 'live_write_denial_check',
23 ],
24 includeRawCredentials: false,
25 allowLiveWrite: false,
26 };
27 }
28
29 async function withSmokeServer({ routerOptions, fn }) {
30 const app = express();
31 app.use(express.json());
32 app.use(createScoolingWriteBackSmokeRouter(routerOptions));
33 const server = http.createServer(app);
34 await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
35 const addr = server.address();
36 assert.ok(addr && typeof addr === 'object');
37 const base = `http://127.0.0.1:${addr.port}`;
38 try {
39 await fn(base);
40 } finally {
41 await new Promise((resolve) => server.close(resolve));
42 }
43 }
44
45 describe('Scooling write-back smoke request validation', () => {
46 it('accepts the exact metadata-only contract', () => {
47 assert.equal(validSmokeRequest(validPayload()), true);
48 });
49
50 it('rejects raw credentials, live writes, production targets, and extra fields', () => {
51 assert.equal(validSmokeRequest({ ...validPayload(), includeRawCredentials: true }), false);
52 assert.equal(validSmokeRequest({ ...validPayload(), allowLiveWrite: true }), false);
53 assert.equal(validSmokeRequest({ ...validPayload(), environment: 'production' }), false);
54 assert.equal(validSmokeRequest({ ...validPayload(), rawCredential: 'secret' }), false);
55 });
56
57 it('requires the full dry-run capability action set', () => {
58 assert.equal(validSmokeRequest({ ...validPayload(), actions: ['metadata_read'] }), false);
59 assert.equal(
60 validSmokeRequest({
61 ...validPayload(),
62 actions: [
63 'metadata_read',
64 'metadata_read',
65 'conflict_check_dry_run',
66 'live_write_denial_check',
67 ],
68 }),
69 false,
70 );
71 });
72 });
73
74 describe('POST /scooling/write-back/smoke', () => {
75 it('is hidden unless explicitly enabled in staging', async () => {
76 await withSmokeServer({
77 routerOptions: {
78 isEnabled: () => false,
79 environment: () => 'staging',
80 canisterUrl: 'https://mock-canister.test',
81 fetchImpl: async () => ({ ok: true }),
82 },
83 fn: async (base) => {
84 const res = await fetch(`${base}/scooling/write-back/smoke`, {
85 method: 'POST',
86 headers: { 'Content-Type': 'application/json' },
87 body: JSON.stringify(validPayload()),
88 });
89 assert.equal(res.status, 404);
90 },
91 });
92
93 await withSmokeServer({
94 routerOptions: {
95 isEnabled: () => true,
96 environment: () => 'production',
97 canisterUrl: 'https://mock-canister.test',
98 fetchImpl: async () => ({ ok: true }),
99 },
100 fn: async (base) => {
101 const res = await fetch(`${base}/scooling/write-back/smoke`, {
102 method: 'POST',
103 headers: { 'Content-Type': 'application/json' },
104 body: JSON.stringify(validPayload()),
105 });
106 assert.equal(res.status, 404);
107 },
108 });
109 });
110
111 it('returns safe metadata only and performs no write calls', async () => {
112 const upstreamCalls = [];
113 await withSmokeServer({
114 routerOptions: {
115 isEnabled: () => true,
116 environment: () => 'staging',
117 canisterUrl: 'https://mock-canister.test',
118 nowIso: () => '2026-05-23T11:00:00.000Z',
119 fetchImpl: async (url, opts) => {
120 upstreamCalls.push({ url: String(url), method: opts?.method || 'GET' });
121 return { ok: true };
122 },
123 },
124 fn: async (base) => {
125 const res = await fetch(`${base}/scooling/write-back/smoke`, {
126 method: 'POST',
127 headers: { 'Content-Type': 'application/json' },
128 body: JSON.stringify(validPayload()),
129 });
130 assert.equal(res.status, 200);
131 const body = await res.json();
132 assert.deepEqual(body, {
133 ok: true,
134 checkedAtIso: '2026-05-23T11:00:00.000Z',
135 targetId: 'phase-2-hosted-knowtation-staging',
136 metadataRead: true,
137 proposalDryRun: true,
138 conflictCheckDryRun: true,
139 liveWriteDenied: true,
140 containsRawCredentials: false,
141 performedLiveWrite: false,
142 });
143 },
144 });
145
146 assert.deepEqual(upstreamCalls, [
147 { url: 'https://mock-canister.test/health', method: 'GET' },
148 ]);
149 });
150
151 it('rejects unsafe payloads without probing upstream metadata', async () => {
152 const upstreamCalls = [];
153 await withSmokeServer({
154 routerOptions: {
155 isEnabled: () => true,
156 environment: () => 'staging',
157 canisterUrl: 'https://mock-canister.test',
158 fetchImpl: async (url, opts) => {
159 upstreamCalls.push({ url: String(url), method: opts?.method || 'GET' });
160 return { ok: true };
161 },
162 },
163 fn: async (base) => {
164 const res = await fetch(`${base}/scooling/write-back/smoke`, {
165 method: 'POST',
166 headers: { 'Content-Type': 'application/json' },
167 body: JSON.stringify({ ...validPayload(), allowLiveWrite: true }),
168 });
169 assert.equal(res.status, 400);
170 const body = await res.json();
171 assert.equal(body.containsRawCredentials, false);
172 assert.equal(body.performedLiveWrite, false);
173 },
174 });
175
176 assert.deepEqual(upstreamCalls, []);
177 });
178
179 it('fails closed when canister metadata is unavailable', async () => {
180 await withSmokeServer({
181 routerOptions: {
182 isEnabled: () => true,
183 environment: () => 'staging',
184 canisterUrl: 'https://mock-canister.test',
185 fetchImpl: async () => ({ ok: false }),
186 },
187 fn: async (base) => {
188 const res = await fetch(`${base}/scooling/write-back/smoke`, {
189 method: 'POST',
190 headers: { 'Content-Type': 'application/json' },
191 body: JSON.stringify(validPayload()),
192 });
193 assert.equal(res.status, 503);
194 const body = await res.json();
195 assert.equal(body.containsRawCredentials, false);
196 assert.equal(body.performedLiveWrite, false);
197 },
198 });
199 });
200 });
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 1 day ago