Problem
Adapters that subclass RegistryWriter override _to_function_module (for framework-specific target/func adaptation) and hand-copy the FunctionModule(...) field list. When an override omits a field, it is dropped silently — no error, no failing test, no warning.
Concretely, annotations were dropped this way in two adapters, so approval/ACL gating (which keys on requires_approval) never fired for their scanned routes. The canonical toolkit RegistryWriter is correct; the structural risk is that every override can re-introduce the gap, and nothing guards it.
Action items (Phase 1 — do now)
-
Centralize the field-mapping. Refactor the base RegistryWriter._to_function_module to construct FunctionModule with all carried fields from ScannedModule (annotations, metadata, documentation, examples, display, tags, version, input/output schemas), and expose a narrow overridable hook for framework-specific work (e.g. _resolve_target(mod) / _adapt_func(func)). Adapters override only the hook → they can no longer drop fields.
-
Round-trip conformance verifier. Provide a reusable test helper (pure apcore + apcore-toolkit, no framework dependency) that asserts: scan → register → get_definition(module_id).annotations preserves requires_approval / destructive (and metadata / examples). Adapters import and run it in their own suites, so the otherwise-invisible bug becomes a red light everywhere.
-
Declare ScannedModule canonical. apcore_toolkit.types.ScannedModule is the single source of truth. At least one adapter forks a local ScannedModule that drifted (missing examples), which makes this repo's own RegistryWriter crash on those modules ('ScannedModule' object has no attribute 'examples'). Document it as canonical and provide typing/guidance so adapters stop forking. (Adapter-side removal of local forks tracked in the adapter repos.)
Scope / notes
- Phase 1 of a two-phase plan. This unblocks the correctness fix across all adapters and prevents recurrence. The apcore-core design work (policy API,
destructive↔approval semantics) is deliberately deferred to Phase 2 and tracked separately in aiperceivable/apcore.
- Version coupling: adapters bump their
apcore-toolkit floor to consume the verifier + refactor.
- Related: adapter fixes in
fastapi-apcore (done), django-apcore (pending).
Related issues
Problem
Adapters that subclass
RegistryWriteroverride_to_function_module(for framework-specific target/func adaptation) and hand-copy theFunctionModule(...)field list. When an override omits a field, it is dropped silently — no error, no failing test, no warning.Concretely,
annotationswere dropped this way in two adapters, so approval/ACL gating (which keys onrequires_approval) never fired for their scanned routes. The canonical toolkitRegistryWriteris correct; the structural risk is that every override can re-introduce the gap, and nothing guards it.Action items (Phase 1 — do now)
Centralize the field-mapping. Refactor the base
RegistryWriter._to_function_moduleto constructFunctionModulewith all carried fields fromScannedModule(annotations,metadata,documentation,examples,display,tags,version, input/output schemas), and expose a narrow overridable hook for framework-specific work (e.g._resolve_target(mod)/_adapt_func(func)). Adapters override only the hook → they can no longer drop fields.Round-trip conformance verifier. Provide a reusable test helper (pure
apcore+apcore-toolkit, no framework dependency) that asserts:scan → register → get_definition(module_id).annotationspreservesrequires_approval/destructive(andmetadata/examples). Adapters import and run it in their own suites, so the otherwise-invisible bug becomes a red light everywhere.Declare
ScannedModulecanonical.apcore_toolkit.types.ScannedModuleis the single source of truth. At least one adapter forks a localScannedModulethat drifted (missingexamples), which makes this repo's ownRegistryWritercrash on those modules ('ScannedModule' object has no attribute 'examples'). Document it as canonical and provide typing/guidance so adapters stop forking. (Adapter-side removal of local forks tracked in the adapter repos.)Scope / notes
destructive↔approval semantics) is deliberately deferred to Phase 2 and tracked separately inaiperceivable/apcore.apcore-toolkitfloor to consume the verifier + refactor.fastapi-apcore(done),django-apcore(pending).Related issues
fastapi-apcore(unreleased)