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>
This commit is contained in:
2026-06-04 13:44:35 -04:00
parent 58d2cb2848
commit 6c5f6f1fba
81 changed files with 9893 additions and 463 deletions

View File

@@ -0,0 +1,167 @@
/**
* Shapes (typed query projection) + Forms (schema / validate / submit) tests.
*
* Shapes prove over-fetch elimination: the projected record carries only the
* declared fields + nested relations, nothing else. Forms prove the three
* roles register as dispatchable `@client` functions carrying the IR's
* `form`/`form-name`/`form-role` meta, and that validate/submit enforce the
* declared field rules.
*/
import { describe, test, expect, beforeEach } from 'bun:test'
import {
clearRegistry,
getFunction,
handleMutationCall,
Shape,
project,
registerForm,
formSchema,
validateForm,
type QueryProjection,
} from '../src'
describe('Shapes — typed query projection', () => {
test('keeps only declared scalar fields', () => {
const projection: QueryProjection = { fields: ['id', 'name'] }
const out = project([{ id: 1, name: 'A', secret: 'x', internal: 42 }], projection)
expect(out).toEqual([{ id: 1, name: 'A' }])
expect(out[0]).not.toHaveProperty('secret')
expect(out[0]).not.toHaveProperty('internal')
})
test('prunes nested relations recursively', () => {
const projection: QueryProjection = {
fields: ['id'],
relations: { orders: { fields: ['total'] } },
}
const out = project(
[{ id: 1, name: 'drop', orders: [{ id: 9, total: 100, hidden: true }] }],
projection,
)
expect(out).toEqual([{ id: 1, orders: [{ total: 100 }] }])
expect(out[0].orders[0]).not.toHaveProperty('hidden')
})
test('handles single-object relation + null', () => {
const projection: QueryProjection = {
fields: ['id'],
relations: { profile: { fields: ['bio'] } },
}
const out = project(
[
{ id: 1, profile: { bio: 'hi', age: 30 } },
{ id: 2, profile: null },
],
projection,
)
expect(out[0]).toEqual({ id: 1, profile: { bio: 'hi' } })
expect(out[1]).toEqual({ id: 2, profile: null })
})
test('Shape.query binds a projection to a source', () => {
const UserShape = new Shape('user', { fields: ['id', 'email'] })
const out = UserShape.query([{ id: 1, email: 'a@b.c', password: 'nope' }])
expect(out).toEqual([{ id: 1, email: 'a@b.c' }])
})
})
describe('Forms — schema / validate / submit', () => {
beforeEach(() => clearRegistry())
const contactForm = {
fields: [
{ name: 'email', type: 'email', required: true, label: 'Email' },
{
name: 'age',
type: 'number',
required: false,
validate: (v: unknown) => (Number(v) < 0 ? 'must be non-negative' : null),
},
],
}
test('formSchema produces field definitions', () => {
const schema = formSchema(contactForm)
expect(schema.fields).toHaveLength(2)
expect(schema.fields[0]).toEqual({
name: 'email',
type: 'email',
required: true,
label: 'Email',
helpText: '',
choices: null,
initial: null,
})
// Default label derived from name when omitted.
expect(schema.fields[1].label).toBe('Age')
})
test('validateForm: required + custom validator', () => {
expect(validateForm(contactForm, { email: 'a@b.c' }).valid).toBe(true)
expect(validateForm(contactForm, {}).errors.email).toEqual(['This field is required.'])
expect(validateForm(contactForm, { email: 'a@b.c', age: -1 }).errors.age).toEqual([
'must be non-negative',
])
})
test('registerForm registers schema + validate + submit with form meta', () => {
const reg = registerForm(contactForm, 'contact', {
submit: async (data) => ({ saved: data.email }),
})
expect(reg).toEqual({ schema: 'contact-schema', validate: 'contact-validate', submit: 'contact-submit' })
for (const [wire, role] of [
['contact-schema', 'schema'],
['contact-validate', 'validate'],
['contact-submit', 'submit'],
] as const) {
const entry = getFunction(wire)
expect(entry).toBeDefined()
expect(entry!.form).toBe(true)
expect(entry!.formName).toBe('contact')
expect(entry!.formRole).toBe(role)
}
})
test('schema function dispatches to the field defs', async () => {
registerForm(contactForm, 'contact')
const r = await handleMutationCall('contact-schema', {})
expect(r.status).toBe(200)
expect(r.body.result.fields).toHaveLength(2)
})
test('validate function dispatches and rejects bad data', async () => {
registerForm(contactForm, 'contact')
const ok = await handleMutationCall('contact-validate', { data: { email: 'a@b.c' } })
expect(ok.body.result.valid).toBe(true)
const bad = await handleMutationCall('contact-validate', { data: {} })
expect(bad.body.result.valid).toBe(false)
expect(bad.body.result.errors.email).toBeDefined()
})
test('submit validates then runs the handler', async () => {
let handled: any = null
registerForm(contactForm, 'contact', {
submit: async (data) => {
handled = data
return { id: 7 }
},
})
const ok = await handleMutationCall('contact-submit', { data: { email: 'a@b.c' } })
expect(ok.body.result).toEqual({ ok: true, result: { id: 7 } })
expect(handled).toEqual({ email: 'a@b.c' })
const bad = await handleMutationCall('contact-submit', { data: {} })
expect(bad.body.result.ok).toBe(false)
expect(bad.body.result.errors.email).toBeDefined()
})
test('submit not registered without a handler', () => {
const reg = registerForm(contactForm, 'noSubmit')
expect(reg.submit).toBeUndefined()
expect(getFunction('noSubmit-submit')).toBeUndefined()
})
})