ontoref-code/examples/catalog-extension/schema-future.ncl

126 lines
3.8 KiB
Text
Raw Normal View History

# Forward-looking schema co-located with the examples — models the
# post-ADR-034 / post-migration-0025 catalog contract so all four example
# kinds typecheck today. Replace these imports with `import "../../.ontoref/catalog/schema.ncl"`
# once migration 0025 has been applied to your project.
#
# Contract decisions are taken from .ontoref/adrs/adr-034-catalog-extensibility-beyond-rust.ncl
# decision block. Keep this file in sync if ADR-034 evolves.
let t_OpKind = [|
'Rust,
'NclTransform,
'Wasm,
'Sidecar,
|] in
let t_NclTransformOp = [| 'Set, 'Append, 'Remove, 'Merge |] in
let t_NclTransformBody = {
target | String,
selector | String,
operation | t_NclTransformOp,
value_expr | String,
} in
let t_WasmBody = {
module_path | String,
export_name | String,
capabilities | Array String,
} in
let t_SidecarBody = {
endpoint | String,
auth_token | String | default = "<from .ontoref/config.ncl::ops.sidecar_token>",
timeout_ms | Number | default = 5000,
} in
let t_ValidatorCategory = [| 'Structural, 'Contextual |] in
let t_WitnessSignature = {
actor_id | String,
algorithm | String | default = "Ed25519",
} in
let t_WitnessShape = {
payload_kind | String,
proof_paths | Array String | default = [],
signature | t_WitnessSignature,
} in
let t_EffectKind = [| 'Insert, 'Update, 'Delete |] in
let t_Effect = {
kind | t_EffectKind,
entity | String,
attrs | Array String,
dimensions | Array String | default = [],
} in
let t_ConstraintBundle = {
pre | Array String | default = [],
inline | Array String | default = [],
post | Array String | default = [],
} in
let t_ActorPolicy = {
roles | Array String | default = [],
} in
let t_ValidationSla = [| 'Synchronous, 'Background |] in
let t_OperationDecl = {
id | String,
description | String,
kind | t_OpKind | default = 'Rust,
body | Dyn | optional,
inputs | { _ : String } | default = {},
constraints | t_ConstraintBundle | default = {},
validation_sla | t_ValidationSla,
effects | Array t_Effect | default = [],
witness_shape | t_WitnessShape,
actor_policy | t_ActorPolicy | default = {},
render_paths | Array String | default = [],
} in
# Ondaod-pre Hard contract — ADR-034 `non-rust-kinds-require-ondaod-pre`.
# Non-Rust ops MUST list "evaluate_ondaod" in constraints.pre. The
# contract is exposed as a SEPARATE annotation that each catalog
# declaration applies after `OperationDecl` so the discipline shows up
# explicitly at every author site, not hidden inside the record shape.
let t_OndaodPreRequired = std.contract.custom (
fun label =>
fun value =>
if value.kind == 'Rust then
'Ok value
else if std.array.any (fun v => v == "evaluate_ondaod") value.constraints.pre then
'Ok value
else
'Error {
message = "ADR-034 `non-rust-kinds-require-ondaod-pre`: op '%{value.id}' (kind = %{std.to_string value.kind}) MUST include \"evaluate_ondaod\" in constraints.pre"
}
) in
# Convenience builder — applies both contracts in the correct order so
# every example reads the same way at the bottom: `... | s.make_op`.
let make_op = fun data =>
let result | t_OperationDecl | t_OndaodPreRequired = data in
result
in
{
OpKind = t_OpKind,
NclTransformBody = t_NclTransformBody,
WasmBody = t_WasmBody,
SidecarBody = t_SidecarBody,
WitnessShape = t_WitnessShape,
WitnessSignature = t_WitnessSignature,
Effect = t_Effect,
EffectKind = t_EffectKind,
ConstraintBundle = t_ConstraintBundle,
ActorPolicy = t_ActorPolicy,
ValidationSla = t_ValidationSla,
OperationDecl = t_OperationDecl,
OndaodPreRequired = t_OndaodPreRequired,
make_op = make_op,
}