// no-secret-leak contract test. // // Verifies that `redactSecrets` strips every key declared as a secret in the // form schema, and is meaningful (not a no-op) — removing the `secret` tag // from a field MUST cause a deliberately-secret value to leak into the result, // proving the test would catch a regression. import { describe, expect, it } from 'vitest'; import { redactSecrets, type FormSchema } from '../index.js'; const SECRET_VALUE = 'hunter2'; const SECRET_REGEX = /password|token|api[_-]?key|secret|credential|bearer/i; describe('redactSecrets', () => { it('drops every key listed in secretFields', () => { const schema: FormSchema = { secretFields: ['password', 'apiKey'] }; const payload = { adminLabel: 'maxy-test', adminDomain: 'maxy.bot', password: SECRET_VALUE, apiKey: 'sk-abc', }; const { redacted, droppedFields, droppedFieldNames } = redactSecrets(payload, schema); expect(redacted).toEqual({ adminLabel: 'maxy-test', adminDomain: 'maxy.bot' }); expect(droppedFields).toBe(2); expect(droppedFieldNames).toEqual(['apiKey', 'password']); }); it('passes every key through when schema has no secretFields', () => { const payload = { mode: 'personal', emailProvided: true }; const { redacted, droppedFields } = redactSecrets(payload, {}); expect(redacted).toEqual(payload); expect(droppedFields).toBe(0); }); it('passes every key through when schema is undefined', () => { const payload = { mode: 'personal' }; const { redacted, droppedFields } = redactSecrets(payload, undefined); expect(redacted).toEqual(payload); expect(droppedFields).toBe(0); }); it('returns empty result for null/undefined payload', () => { expect(redactSecrets(null, { secretFields: ['x'] })).toEqual({ redacted: {}, droppedFields: 0, droppedFieldNames: [], }); expect(redactSecrets(undefined, undefined)).toEqual({ redacted: {}, droppedFields: 0, droppedFieldNames: [], }); }); it('preserves falsy non-secret values (false, 0, empty string, null)', () => { const payload = { a: false, b: 0, c: '', d: null, secret: 's' }; const { redacted } = redactSecrets(payload, { secretFields: ['secret'] }); expect(redacted).toEqual({ a: false, b: 0, c: '', d: null }); }); it('does not count secret keys absent from payload', () => { const schema: FormSchema = { secretFields: ['password', 'missingField'] }; const { droppedFields, droppedFieldNames } = redactSecrets({ password: SECRET_VALUE }, schema); expect(droppedFields).toBe(1); expect(droppedFieldNames).toEqual(['password']); }); it('drops a secret key regardless of its value shape', () => { const schema: FormSchema = { secretFields: ['password'] }; const cases: Array<{ password: unknown }> = [ { password: 'string-value' }, { password: 42 }, { password: null }, { password: { nested: 'object' } }, { password: ['array', 'of', 'strings'] }, ]; for (const c of cases) { const { redacted } = redactSecrets(c as Record, schema); expect(redacted).not.toHaveProperty('password'); } }); it('CONTRACT: no recorded property value contains a secret regex match (cloudflare-setup-form)', () => { // Synthetic cloudflare submission shape — mirrors CloudflareSetupRequest // including both the operator-supplied secret (password) and the // wire-protocol envelope (session_key, messageId) the schema also drops. const cloudflareSchema: FormSchema = { secretFields: ['password', 'session_key', 'messageId'] }; const payload = { adminLabel: 'maxy-test', adminDomain: 'maxy.bot', publicLabel: 'public', publicDomain: 'maxy.bot', apex: 'maxy.bot', password: SECRET_VALUE, tunnelName: 'maxy-test', session_key: 'sk-conversation-correlation-12345678', messageId: '11111111-2222-3333-4444-555555555555', }; const { redacted } = redactSecrets(payload, cloudflareSchema); // Scan every recorded value for any known-secret regex match. for (const [key, value] of Object.entries(redacted)) { const stringified = JSON.stringify(value); expect(stringified, `field ${key} carried a secret-shaped value`).not.toMatch(SECRET_REGEX); expect(stringified, `field ${key} carried the secret literal`).not.toContain(SECRET_VALUE); } // Wire-envelope fields must also be absent from recorded props. expect(redacted).not.toHaveProperty('session_key'); expect(redacted).not.toHaveProperty('messageId'); }); it('CONTRACT (falsifiability): removing the secret tag causes the password to leak — proves the test is meaningful', () => { // This test is the canary that proves the no-secret-leak guarantee comes // from the schema, not from coincidence. With `secretFields` empty (the // schema-author forgot to tag `password`), the value MUST leak into the // recorded payload — otherwise the contract test above would still pass // even with a broken schema, and would catch nothing. const brokenSchema: FormSchema = { secretFields: [] }; const payload = { adminLabel: 'maxy-test', password: SECRET_VALUE }; const { redacted } = redactSecrets(payload, brokenSchema); expect(redacted.password).toBe(SECRET_VALUE); expect(JSON.stringify(redacted)).toContain(SECRET_VALUE); }); });