Files
mizan/backends/mizan-ts/tests/token.test.ts
Ryth Azhur 6c5f6f1fba AFI parity: close all 35 gaps — every adapter wires every AFI-common capability
The conformance board (tests/afi/test_capability_parity.py) is now fully green:
90 capability cells + 4 meta-locks + 3 codegen byte-parity = 97 passed. The
gaps the prose table used to launder as "Django-only" / "out of scope" are
wired, against the pinned-spec model (single-authored spec, byte-identical
conformance across languages) — never per-language reimplementation.

FastAPI — edge_manifest + PSR (logic single-sourced in mizan_core.manifest),
WebSocket RPC (/ws/ through the shared dispatch), SSR (the framework-agnostic
SSRBridge relocated to mizan_core.ssr; Django rides it from there), Shapes
(SQLAlchemy projection, same declaration surface as django-readers), Forms
(Pydantic schema/validate/submit).

Rust (Axum + Tauri + cores/mizan-rust) — X-Mizan-Invalidate header, auth=
enforcement, origin HMAC cache, edge manifest + PSR, WebSocket handler / IPC
subscription channel, multipart upload, SSR bridge, Shapes, Forms; JWT/MWT
mint+verify and cache-key derivation byte-pinned to the Python reference
(cache_keys_pin, token_pin, invalidate_header_pin).

TypeScript — a KDL IR emitter byte-identical to the Python build_ir (so a TS
backend can feed the codegen — the largest gap), multipart upload, session-init,
WebSocket transport, SSR bridge, JWT/MWT mint (pinned to Python), Shapes, Forms.

Verified in the merged tree: core 25, fastapi 74, django 353/21-skip,
mizan-rust (incl. cross-language pins) green, axum 10, tauri 8, mizan-ts 103/2-skip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 13:44:35 -04:00

254 lines
8.9 KiB
TypeScript

/**
* MWT / JWT token tests — decode round-trip + cross-language byte-parity pins
* against the live Python mint (`cores/mizan-python`).
*/
import { describe, test, expect } from 'bun:test'
import { createHmac, createHash } from 'crypto'
import { execFileSync } from 'child_process'
import { existsSync } from 'fs'
import { resolve } from 'path'
import {
decodeMwt,
decodeJwtBearer,
identityFromMwt,
signMwt,
computePermissionKey,
createAccessToken,
createRefreshToken,
type MintUser,
} from '../src'
function b64url(buf: Buffer | string): string {
return Buffer.from(buf).toString('base64url')
}
/** Mint an HS256 MWT with node crypto, mirroring Python create_mwt. */
function mint(payload: Record<string, any>, secret: string, kid = 'v1'): string {
const header = b64url(JSON.stringify({ alg: 'HS256', kid, typ: 'JWT' }))
const body = b64url(JSON.stringify(payload))
const sig = createHmac('sha256', secret).update(`${header}.${body}`).digest('base64url')
return `${header}.${body}.${sig}`
}
const SECRET = 'round-trip-secret'
const now = Math.floor(Date.now() / 1000)
function basePayload(overrides: Record<string, any> = {}) {
return {
sub: '7',
staff: true,
super: false,
pkey: 'abc123',
aud: 'mizan',
iat: now,
nbf: now,
exp: now + 300,
...overrides,
}
}
describe('MWT round-trip', () => {
test('valid token decodes', () => {
const token = mint(basePayload(), SECRET)
const p = decodeMwt(token, SECRET)
expect(p).not.toBeNull()
expect(p!.sub).toBe('7')
expect(p!.staff).toBe(true)
expect(p!.super).toBe(false)
expect(p!.pkey).toBe('abc123')
expect(p!.kid).toBe('v1')
expect(p!.aud).toBe('mizan')
})
test('identityFromMwt maps claims', () => {
const token = mint(basePayload({ sub: '99', staff: false, super: true }), SECRET)
const p = decodeMwt(token, SECRET)!
expect(identityFromMwt(p)).toEqual({
isAuthenticated: true,
isStaff: false,
isSuperuser: true,
id: 99,
})
})
test('decodeJwtBearer strips Bearer prefix', () => {
const token = mint(basePayload(), SECRET)
const p = decodeJwtBearer(`Bearer ${token}`, SECRET)
expect(p).not.toBeNull()
expect(p!.sub).toBe('7')
})
test('null on tampered signature', () => {
const token = mint(basePayload(), SECRET)
const tampered = token.slice(0, -2) + (token.endsWith('AA') ? 'BB' : 'AA')
expect(decodeMwt(tampered, SECRET)).toBeNull()
})
test('null on wrong secret', () => {
const token = mint(basePayload(), SECRET)
expect(decodeMwt(token, 'other-secret')).toBeNull()
})
test('null on expired exp', () => {
const token = mint(basePayload({ exp: now - 10 }), SECRET)
expect(decodeMwt(token, SECRET)).toBeNull()
})
test('null on future nbf', () => {
const token = mint(basePayload({ nbf: now + 1000 }), SECRET)
expect(decodeMwt(token, SECRET)).toBeNull()
})
test('null on wrong aud', () => {
const token = mint(basePayload({ aud: 'other' }), SECRET)
expect(decodeMwt(token, SECRET)).toBeNull()
})
test('null on malformed token', () => {
expect(decodeMwt('not.a.jwt', SECRET)).toBeNull()
expect(decodeMwt('onlyonepart', SECRET)).toBeNull()
expect(decodeMwt('', SECRET)).toBeNull()
})
})
describe('MWT cross-language pin (Python create_mwt)', () => {
const TOKEN = 'eyJhbGciOiJIUzI1NiIsImtpZCI6InYxIiwidHlwIjoiSldUIn0.eyJzdWIiOiI0MiIsInN0YWZmIjp0cnVlLCJzdXBlciI6ZmFsc2UsInBrZXkiOiIwZTk5OGE5ZmYxNjkwNDYzN2EwM2QyZWEwZmJkYmY5NzQyOTdhOWQxYTVkMjViOGQ0Mjk0ZmE4ODIxMTVlNDU3IiwiYXVkIjoibWl6YW4iLCJpYXQiOjE3MDAwMDAwMDAsIm5iZiI6MTcwMDAwMDAwMCwiZXhwIjo0MTAyNDQ0ODAwfQ._V92JXiLSLXoyuSwbNvvJjwzgmczmC7dvX34kVSLIa8'
const PIN_SECRET = 'pin-test-secret-mwt'
test('decodes the Python-minted token', () => {
const p = decodeMwt(TOKEN, PIN_SECRET)
expect(p).not.toBeNull()
expect(p!.sub).toBe('42')
expect(p!.staff).toBe(true)
expect(p!.super).toBe(false)
expect(p!.pkey).toBe('0e998a9ff16904637a03d2ea0fbdbf974297a9d1a5d25b8d4294fa882115e457')
expect(p!.kid).toBe('v1')
expect(p!.aud).toBe('mizan')
})
test('identity from Python-minted token', () => {
const p = decodeMwt(TOKEN, PIN_SECRET)!
expect(identityFromMwt(p)).toEqual({
isAuthenticated: true,
isStaff: true,
isSuperuser: false,
id: 42,
})
})
})
// ─── Mint: round-trip + cross-language byte-parity ────────────────────────────
const REPO_ROOT = resolve(import.meta.dir, '../../..')
const MIZAN_PYTHON = resolve(REPO_ROOT, 'cores/mizan-python')
const UV_AVAILABLE = (() => {
try {
execFileSync('uv', ['--version'], { stdio: 'ignore' })
return existsSync(resolve(MIZAN_PYTHON, 'pyproject.toml'))
} catch {
return false
}
})()
/**
* Run a Python snippet against cores/mizan-python and return stdout (trimmed).
* `time.time` is pinned so the production mint functions are deterministic.
*/
function py(snippet: string): string {
return execFileSync('uv', ['run', '--project', MIZAN_PYTHON, 'python', '-c', snippet], {
encoding: 'utf-8',
}).trim()
}
describe('MWT mint — round-trip', () => {
const SECRET = 'mint-roundtrip-secret'
test('signMwt produces a token decodeMwt accepts', () => {
const user: MintUser = { pk: 7, isStaff: true, isSuperuser: false, permissions: ['a.view', 'a.edit'] }
const token = signMwt(user, SECRET, { now: Math.floor(Date.now() / 1000) })
const p = decodeMwt(token, SECRET)
expect(p).not.toBeNull()
expect(p!.sub).toBe('7')
expect(p!.staff).toBe(true)
expect(p!.super).toBe(false)
expect(p!.kid).toBe('v1')
expect(p!.aud).toBe('mizan')
// pkey is the permission hash, surviving the round-trip.
expect(p!.pkey).toBe(computePermissionKey(user))
})
test('computePermissionKey matches the documented blob hash', () => {
const user: MintUser = { pk: 1, isStaff: true, isSuperuser: false, permissions: ['z', 'a'] }
// "1:0:a,z" — staff:super:sorted-perms.
const expected = createHash('sha256').update('1:0:a,z', 'utf-8').digest('hex')
expect(computePermissionKey(user)).toBe(expected)
})
})
describe('MWT mint — cross-language pin (Python create_mwt)', () => {
const SECRET = 'pin-mint-secret-mwt'
const NOW = 1700000000
test.skipIf(!UV_AVAILABLE)('TS signMwt byte-identical to Python create_mwt', () => {
const user: MintUser = {
pk: 42,
isStaff: true,
isSuperuser: false,
permissions: ['app.view_thing', 'app.change_thing'],
}
const tsToken = signMwt(user, SECRET, { ttl: 300, now: NOW })
// Drive the REAL create_mwt with time.time pinned to NOW and a
// user stub whose get_all_permissions returns the same perms.
const pyToken = py(String.raw`
import time, sys
time.time = lambda: ${NOW}
from mizan_core.mwt import create_mwt
class U:
pk = 42
is_staff = True
is_superuser = False
def get_all_permissions(self):
return {"app.view_thing", "app.change_thing"}
sys.stdout.write(create_mwt(U(), ${JSON.stringify(SECRET)}, ttl=300))
`)
expect(tsToken).toBe(pyToken)
})
})
describe('JWT mint — cross-language pin (Python create_access/refresh_token)', () => {
const SECRET = 'pin-mint-secret-jwt'
const NOW = 1700000000
const config = { privateKey: SECRET, accessTokenExpiresIn: 300, refreshTokenExpiresIn: 604800 }
const claims = { userId: 42, sessionKey: 'sess-abc', isStaff: true, isSuperuser: false }
test.skipIf(!UV_AVAILABLE)('TS createAccessToken byte-identical to Python', () => {
const tsToken = createAccessToken(claims, config, NOW)
const pyToken = py(String.raw`
import time, sys
time.time = lambda: ${NOW}
from mizan_core.auth.jwt import JWTConfig, create_access_token
cfg = JWTConfig(private_key=${JSON.stringify(SECRET)}, public_key=${JSON.stringify(SECRET)})
sys.stdout.write(create_access_token(42, "sess-abc", cfg, is_staff=True, is_superuser=False))
`)
expect(tsToken).toBe(pyToken)
})
test.skipIf(!UV_AVAILABLE)('TS createRefreshToken byte-identical to Python', () => {
const tsToken = createRefreshToken(claims, config, NOW)
const pyToken = py(String.raw`
import time, sys
time.time = lambda: ${NOW}
from mizan_core.auth.jwt import JWTConfig, create_refresh_token
cfg = JWTConfig(private_key=${JSON.stringify(SECRET)}, public_key=${JSON.stringify(SECRET)})
sys.stdout.write(create_refresh_token(42, "sess-abc", cfg, is_staff=True, is_superuser=False))
`)
expect(tsToken).toBe(pyToken)
})
})