This is the smallest golden RFC-00D1 example in the repo.
It shows a real host directory import into CanonFS, a real export back out to a host directory, and the built-in policy-profile surface that currently ships as the narrow v1 candidate contract.
If you want the single frozen v1 contract fixture set, start in:
examples/storage-and-canonfs/canonfs-interchange/v1/For the current build-against boundary, pair this example with:
spec/rfcs/RFC-00D1-canonfs-foreign-filesystem-interchange.mdexamples/storage-and-canonfs/canonfs-interchange/v1/README.mdThe current RFC-00D1 v1 candidate surface is intentionally narrow.
Treat the following as stable enough to build against today:
canonfs importcanonfs exportt81.canonfs-import.v1t81.canonfs-export.v1t81.canonfs-import-provenance.v1t81.canonfs-export-provenance.v1t81.canonfs-interchange-manifest.v1host-file and host-directoryprovenance_schema and manifest_schemakind, message, code, reasonpermissive, import-only, export-only,
deny-allStill explicitly deferred from full v1 promotion:
input/alpha.txtinput/nested/beta.txtpolicy-allow-alpha-only.aplpolicy-deny-all.aplpolicy-allow-example-inputs.aplFrom the repo root:
tmp_root="$(mktemp -d)"
canon_root="$tmp_root/.t81_canonfs"
export_root="$tmp_root/exported"
build/t81 canonfs import \
examples/storage-and-canonfs/canonfs-interchange/input \
--canonfs-root "$canon_root" \
--json
Expected shape:
t81.canonfs-import.v1host-directoryokallowedpermissivet81.canonfs-import-provenance.v1t81.canonfs-interchange-manifest.v1manifest_ref populatedExport the returned manifest_ref back to a host directory:
manifest_ref="<manifest_ref from previous step>"
build/t81 canonfs export \
"$manifest_ref" \
--canonfs-root "$canon_root" \
--out "$export_root" \
--json
Expected shape:
t81.canonfs-export.v1host-directoryokallowedpermissivet81.canonfs-export-provenance.v1t81.canonfs-interchange-manifest.v1materialized_paths includes alpha.txt and nested/beta.txtYou can verify the exported payloads directly:
cat "$export_root/alpha.txt"
cat "$export_root/nested/beta.txt"
This lane also supports explicit policy-profile denial without needing an extra policy file:
build/t81 canonfs import \
examples/storage-and-canonfs/canonfs-interchange/input \
--canonfs-root "$canon_root" \
--policy-profile export-only \
--json
Expected shape:
errordeniedexport-onlypolicy-failurecanonfs-policy-deniedpolicy_deniedThe current built-in profiles are intentionally narrow and deterministic:
permissive
allow import and export unless an explicit policy document/evaluator denies the requestimport-only
allow canonfs import and deny canonfs export before host materializationexport-only
allow canonfs export and deny canonfs import before CanonFS storage writesdeny-all
deny both canonfs import and canonfs exportThe current profile surface is about pre-side-effect admission control, not rich content policy. In other words:
policy_result, policy_profile, and a
structured error with kind, code, reason, and messagekind, message, code, reasonBuilt-in profiles and explicit policy files are conjunctive:
canonfs import or canonfs export
is allowed at allok, error, or partial without adding new
profile namesThis example directory also includes two small Axion policy files that work with the current CanonFS interchange lane:
policy-allow-alpha-only.apl
allows only input/alpha.txt, which makes the checked-in directory import and
export paths return partial instead of all-or-nothingpolicy-deny-all.apl
denies CanonFS import/export through policy evaluation even when the built-in
profile is still permissivepolicy-allow-example-inputs.apl
allows only the two checked-in example input objects by hashValidate them directly:
build/t81 policy validate \
examples/storage-and-canonfs/canonfs-interchange/policy-allow-alpha-only.apl \
--json
build/t81 policy validate \
examples/storage-and-canonfs/canonfs-interchange/policy-deny-all.apl \
--json
build/t81 policy validate \
examples/storage-and-canonfs/canonfs-interchange/policy-allow-example-inputs.apl \
--json
Partial import using the checked-in alpha-only policy:
build/t81 canonfs import \
examples/storage-and-canonfs/canonfs-interchange/input \
--canonfs-root "$canon_root" \
--policy examples/storage-and-canonfs/canonfs-interchange/policy-allow-alpha-only.apl \
--json
Expected shape:
partialpartialpermissivet81.canonfs-import-provenance.v1t81.canonfs-interchange-manifest.v1imported_paths includes alpha.txterrors[0].reason: policy_deniederrors[0].message mentions nested/beta.txtPolicy denial through a checked-in file:
build/t81 canonfs import \
examples/storage-and-canonfs/canonfs-interchange/input \
--canonfs-root "$canon_root" \
--policy examples/storage-and-canonfs/canonfs-interchange/policy-deny-all.apl \
--json
Expected shape:
errordeniedpolicy_deniedThe same checked-in policy file can deny export under the default permissive profile once you already have a manifest or object ref:
build/t81 canonfs export \
"$manifest_ref" \
--canonfs-root "$canon_root" \
--policy examples/storage-and-canonfs/canonfs-interchange/policy-deny-all.apl \
--out "$export_root" \
--json
Expected shape:
errordeniedpermissivepolicy-failurepolicy_deniedPolicy allowlist using the checked-in example input hashes:
build/t81 canonfs import \
examples/storage-and-canonfs/canonfs-interchange/input \
--canonfs-root "$canon_root" \
--policy examples/storage-and-canonfs/canonfs-interchange/policy-allow-example-inputs.apl \
--json
Expected shape:
okpermissiveYou can also see the same narrowing effect on export by first importing the
directory under the permissive default, then exporting the returned
manifest_ref with the alpha-only policy:
build/t81 canonfs export \
"$manifest_ref" \
--canonfs-root "$canon_root" \
--policy examples/storage-and-canonfs/canonfs-interchange/policy-allow-alpha-only.apl \
--out "$export_root" \
--json
Expected shape:
partialpartialpermissivet81.canonfs-export-provenance.v1t81.canonfs-interchange-manifest.v1materialized_paths includes alpha.txtmaterialized_paths does not include nested/beta.txterrors[0].reason: policy_deniederrors[0].message mentions nested/beta.txterrors[0] is emitted in stable field order:
kind, message, code, reasonThe current contract also distinguishes target-side export failures from source or policy failures. One small reproducible case is exporting a single-file CanonFS object to a path that already exists as a directory:
blocked_out="$tmp_root/already-a-directory"
mkdir -p "$blocked_out"
build/t81 canonfs export \
"$hash" \
--canonfs-root "$canon_root" \
--out "$blocked_out" \
--json
Expected shape:
t81.canonfs-export.v1errortarget-failurecanonfs-export-target-open-failedtarget_open_failedcanonfs_interchange_test.