Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,26 @@ and an external-target smoke remain required.

## Inactive control policy-set validator

`control/v1/` defines a canonical identity bundle for six later Control foundation
policies: duty separation, sandbox, credentials, risk gates, kill switch, and
immutable evidence. Its validator checks exact immutable policy and decision refs;
it does not contain or evaluate those policies.
`control/v1/` defines the canonical shape and order for six Control foundation
policies: credentials, duty separation, immutable evidence, kill switch, risk
gates, and sandbox. Its validator checks the set shape and relations. It does not
contain or evaluate those policies.

The package stays inactive and fail-closed. It grants no authority, activates no
profile, reads no credential, launches no adapter, and performs no external write.
Later bounded units own each policy body and its enforcement.

## Inactive Control foundation roll-up

`control/v1/control-policy-set.json` pins the six shipped policy and decision files
in the required order. It also pins their shared core contract generation and
package. The focused test recomputes all twelve file digests and the core package
closure rather than trusting the refs in the set.

This is a static, repo-only identity bundle. It adds no aggregator runtime and
makes no enforcement, qualification, approval, authority, activation, or external
effect claim. The set stays inactive and fails closed.

## Inactive duty-separation evaluator

`control/v1/evaluate-duty.sh` checks one public core v2 stage tuple against the
Expand Down
12 changes: 12 additions & 0 deletions RESTORE.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,18 @@ The proof validates only the canonical six-section identity bundle. It does not
evaluate a policy, grant authority, activate a profile, or enforce sandbox,
credential, risk, kill-switch, or evidence behavior.

Restore the two paths in the manifest's inactive Control foundation roll-up block,
then run:

```sh
bash scripts/test/control-foundation-rollup.test.sh
```

This recomputes the six policy and six decision file identities, their common core
generation and package closure, and the inactive fail-closed boundary. It adds no
aggregator runtime and makes no enforcement, qualification, authority, activation,
or external-effect claim.

Restore the five paths in the manifest's inactive duty-separation block, then run:

```sh
Expand Down
4 changes: 4 additions & 0 deletions ci/required-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,7 @@ control/v1/evidence-integrity-decision.json
control/v1/evidence-integrity.jq
control/v1/evaluate-evidence-integrity.sh
scripts/test/control-evidence-integrity.test.sh

# Inactive Control foundation policy roll-up
control/v1/control-policy-set.json
scripts/test/control-foundation-rollup.test.sh
1 change: 1 addition & 0 deletions control/v1/control-policy-set.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"body":{"activation_state":"inactive","core_contract":{"generation_id":"g-392d20099dfa99872764009b268c8871914b4dbc0da467ec346baa921818ae3e","package_ref":{"content_id":"core-contract-package.v2","media_type":"application/vnd.ystack.core-contract+json","sha256":"005431c5c7e3a39dc3ab75dfcafd0f09359331667fdcacb140514a4384592716"},"semantic_identity":"core.contracts.v2"},"fail_mode":"closed","policy_version":"v1","sections":[{"decision_ref":{"content_id":"control-decision.credential-policy","media_type":"application/vnd.ystack.control-decision+json","sha256":"006b78ca2a937f77a870f9b5a9a0137c45702c2e6879979d6112025e90176cc0"},"policy_ref":{"content_id":"control-policy.credential-policy","media_type":"application/vnd.ystack.control-policy+json","sha256":"1ca546132d904900e00db532d5f2091336a8dd9f426be591ac7e9d91f47a69f3"},"section_id":"credential-policy"},{"decision_ref":{"content_id":"control-decision.duty-separation","media_type":"application/vnd.ystack.control-decision+json","sha256":"08f8b496a689ab6fefa976de495fa13e1f9d954cd2b33ee44acd3c70022b4697"},"policy_ref":{"content_id":"control-policy.duty-separation","media_type":"application/vnd.ystack.control-policy+json","sha256":"b33a4022c74c8a1ccb06674c080adf2fc106561c426a7d1dd30fdb9865531dbb"},"section_id":"duty-separation"},{"decision_ref":{"content_id":"control-decision.evidence-integrity","media_type":"application/vnd.ystack.control-decision+json","sha256":"2d73d496b1535b6015843ff4c0c250bc77e476532c088ef9d7885ef393849327"},"policy_ref":{"content_id":"control-policy.evidence-integrity","media_type":"application/vnd.ystack.control-policy+json","sha256":"171b89c49c7dd6a58e4c5aa6ca13e8c95d109acf7f67429ecb33fcf1dae7582a"},"section_id":"evidence-integrity"},{"decision_ref":{"content_id":"control-decision.kill-switch","media_type":"application/vnd.ystack.control-decision+json","sha256":"213516a567c9269dcef1085a7fd84a18ab05f61cfc8042be801f1c0725ba27d2"},"policy_ref":{"content_id":"control-policy.kill-switch","media_type":"application/vnd.ystack.control-policy+json","sha256":"60a1171f13fa763076b31c0d65a3a54e70d2af28860e3a6da9ed6bb0038a15f5"},"section_id":"kill-switch"},{"decision_ref":{"content_id":"control-decision.risk-gates","media_type":"application/vnd.ystack.control-decision+json","sha256":"4e7747a495106727a3cda68f8097fae5687425608c3d66d790182e9747359d5b"},"policy_ref":{"content_id":"control-policy.risk-gates","media_type":"application/vnd.ystack.control-policy+json","sha256":"0286be22ec3d3a31be8e2c00c5e57a5b674c3f6b0e6d03c87a670e51e3141bed"},"section_id":"risk-gates"},{"decision_ref":{"content_id":"control-decision.sandbox","media_type":"application/vnd.ystack.control-decision+json","sha256":"c3e89800147d55f7c726ec66c82031915a4220d3eb7867e143f60d7026223bbd"},"policy_ref":{"content_id":"control-policy.sandbox","media_type":"application/vnd.ystack.control-policy+json","sha256":"4afb62e44fd3ad055d157ee23bfcf2917811b9ec05e4923eaa989d95d53c0a5e"},"section_id":"sandbox"}]},"id":"control-policy-set.v1","kind":"control_policy_set","schema_version":1}
272 changes: 272 additions & 0 deletions scripts/test/control-foundation-rollup.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
#!/usr/bin/env bash
# shellcheck disable=SC2016
set -euo pipefail
export LC_ALL=C
umask 077

root=$(CDPATH='' cd -P -- "${BASH_SOURCE[0]%/*}/../.." && pwd -P)
policy_set="$root/control/v1/control-policy-set.json"
validator="$root/control/v1/validate.sh"
core_wrapper="$root/scripts/core-contract.sh"
core_registry="$root/core/v2/generation-registry.json"
tmp=$(/usr/bin/mktemp -d "${TMPDIR:-/tmp}/ystack-control-rollup-test.XXXXXX")
tmp=$(CDPATH='' cd -P -- "$tmp" && pwd -P)
download=''

cleanup() {
if [ -n "$download" ] && [ -f "$download" ]; then
/bin/rm -f -- "$download"
fi
/bin/rm -rf -- "$tmp"
}
trap cleanup EXIT
fail() { /usr/bin/printf 'FAIL: %s\n' "$1" >&2; exit 1; }
passes=0
pass() { passes=$((passes + 1)); /usr/bin/printf 'ok %s - %s\n' "$passes" "$1"; }
sha256_path() { /usr/bin/shasum -a 256 "$1" | /usr/bin/awk '{print $1}'; }
sha256_text() {
/usr/bin/printf '%s' "$1" | /usr/bin/shasum -a 256 | /usr/bin/awk '{print $1}'
}

platform=$(/usr/bin/uname -s):$(/usr/bin/uname -m)
case "$platform" in
Darwin:*)
jq_asset=jq-osx-amd64
jq_sha=5c0a0a3ea600f302ee458b30317425dd9632d1ad8882259fcaf4e9b868b2b1ef
;;
Linux:x86_64)
jq_asset=jq-linux64
jq_sha=af986793a515d500ab2d35f8d2aecd656e764504b789b66d7e1a0b727a124c44
;;
*) fail "unsupported host $platform" ;;
esac
jq_cache_dir="${TMPDIR:-/tmp}/ystack-portable-core-jq16"
/bin/mkdir -p "$jq_cache_dir"
jq_cache="$jq_cache_dir/$jq_asset"
if [ ! -f "$jq_cache" ] || [ "$(sha256_path "$jq_cache")" != "$jq_sha" ]; then
download=$(/usr/bin/mktemp "$jq_cache_dir/.jq-1.6.XXXXXX")
/usr/bin/curl --proto '=https' --tlsv1.2 -fsSL \
"https://github.com/jqlang/jq/releases/download/jq-1.6/$jq_asset" \
-o "$download"
[ "$(sha256_path "$download")" = "$jq_sha" ] || fail 'jq release digest'
/bin/chmod 0555 "$download"
/bin/mv "$download" "$jq_cache"
download=''
fi
[ "$(sha256_path "$jq_cache")" = "$jq_sha" ] || fail 'jq digest'
bin="$tmp/bin"
/bin/mkdir -m 0700 "$bin"
/bin/cp "$jq_cache" "$bin/jq"
/bin/chmod 0555 "$bin/jq"
jq_bin="$bin/jq"
[ "$("$jq_bin" --version)" = jq-1.6 ] || fail 'jq identity'

"$jq_bin" -s -S -c 'if length==1 then .[0] else error("root-count") end' \
"$policy_set" >"$tmp/canonical.json" || fail 'shipped set parse'
/usr/bin/cmp -s "$policy_set" "$tmp/canonical.json" || fail 'canonical shipped set'
validator_out="$tmp/validator.out"
validator_err="$tmp/validator.err"
PATH="$bin:/usr/bin:/bin" "$validator" validate "$policy_set" \
>"$validator_out" 2>"$validator_err" || fail 'shipped set validation'
[ ! -s "$validator_out" ] && [ ! -s "$validator_err" ] || fail 'validator output'
pass 'canonical shipped set passes the v1 validator'

generation=$(/usr/bin/sed -n \
"s/^PORTABLE_CORE_GENERATION='\(g-[0-9a-f]\{64\}\)'$/\1/p" "$core_wrapper") ||
fail 'selected generation'
[[ "$generation" =~ ^g-[0-9a-f]{64}$ ]] || fail 'selected generation shape'
"$jq_bin" -e --arg generation "$generation" '
[.[] | select(.generation_id==$generation and
.semantic_identity=="core.contracts.v2")] | length==1
' "$core_registry" >/dev/null || fail 'selected generation registry identity'
generation_sha=$(sha256_text "$generation")

closure_members="$tmp/core-closure-members.tsv"
closure_paths=(
scripts/core-contract.sh
core/v2/generation-registry.json
"core/v2/generations/$generation/contracts.jq"
"core/v2/generations/$generation/core-ingress.sh"
"core/v2/generations/$generation/modules/profile_graph.jq"
"core/v2/generations/$generation/modules/result_facts.jq"
"core/v2/generations/$generation/modules/result_truth.jq"
"core/v2/generations/$generation/modules/schema.jq"
"core/v2/generations/$generation/modules/stage_request.jq"
)
: >"$closure_members"
for closure_path in "${closure_paths[@]}"; do
/usr/bin/printf '%s\t%s\n' "$closure_path" \
"$(sha256_path "$root/$closure_path")" >>"$closure_members"
done
closure_descriptor=$("$jq_bin" -Rn -S -c --arg generation_sha "$generation_sha" '
[inputs | split("\t") | {path:.[0],sha256:.[1]}] as $members |
{schema_version:1,kind:"core_contract_package_closure",
semantic_identity:"core.contracts.v2",
selected_generation_id_sha256:$generation_sha,members:$members}
' <"$closure_members")
core_package_sha=$(sha256_text "$closure_descriptor")
"$jq_bin" -e --arg generation "$generation" --arg package_sha "$core_package_sha" '
.id=="control-policy-set.v1" and
.body.core_contract=={
generation_id:$generation,
package_ref:{content_id:"core-contract-package.v2",
media_type:"application/vnd.ystack.core-contract+json",sha256:$package_sha},
semantic_identity:"core.contracts.v2"}
' "$policy_set" >/dev/null || fail 'shared core contract closure'
pass 'selected core generation and package closure are exact'

sections=(
credential-policy duty-separation evidence-integrity
kill-switch risk-gates sandbox
)
policy_files=(
credential-policy.json duty-separation-policy.json evidence-integrity-policy.json
kill-switch-policy.json risk-gates-policy.json sandbox-policy.json
)
decision_files=(
credential-policy-decision.json duty-separation-decision.json
evidence-integrity-decision.json kill-switch-decision.json
risk-gates-decision.json sandbox-decision.json
)
policy_media=application/vnd.ystack.control-policy+json
decision_media=application/vnd.ystack.control-decision+json

check_closure() {
local input=$1 index section policy decision policy_sha decision_sha
PATH="$bin:/usr/bin:/bin" "$validator" validate "$input" >/dev/null 2>&1 || return 1
"$jq_bin" -e --arg generation "$generation" --arg package_sha "$core_package_sha" '
.body.core_contract=={
generation_id:$generation,
package_ref:{content_id:"core-contract-package.v2",
media_type:"application/vnd.ystack.core-contract+json",sha256:$package_sha},
semantic_identity:"core.contracts.v2"}
' "$input" >/dev/null || return 1
for index in 0 1 2 3 4 5; do
section=${sections[$index]}
policy="$root/control/v1/${policy_files[$index]}"
decision="$root/control/v1/${decision_files[$index]}"
policy_sha=$(sha256_path "$policy")
decision_sha=$(sha256_path "$decision")
"$jq_bin" -e --argjson index "$index" --arg section "$section" \
--arg policy_media "$policy_media" --arg decision_media "$decision_media" \
--arg policy_sha "$policy_sha" --arg decision_sha "$decision_sha" '
.body.sections[$index]=={
decision_ref:{content_id:("control-decision."+$section),
media_type:$decision_media,sha256:$decision_sha},
policy_ref:{content_id:("control-policy."+$section),
media_type:$policy_media,sha256:$policy_sha},section_id:$section}
' "$input" >/dev/null || return 1
done
}

direct_core_count=0
for index in 0 1 2 3 4 5; do
section=${sections[$index]}
policy="$root/control/v1/${policy_files[$index]}"
decision="$root/control/v1/${decision_files[$index]}"
policy_sha=$(sha256_path "$policy")
decision_sha=$(sha256_path "$decision")
"$jq_bin" -e --arg section "$section" --arg policy_sha "$policy_sha" '
.schema_version==1 and .id==("control-decision."+$section) and
.body.activation_state=="inactive" and .body.fail_mode=="closed" and
.body.decision=="allow-observation-only-evaluation" and
.body.policy_ref=={content_id:("control-policy."+$section),
media_type:"application/vnd.ystack.control-policy+json",sha256:$policy_sha} and
.body.semantics.authority_effect=="none" and
(.body.semantics.qualification_effect // "none")=="none" and
(.body.semantics.storage_effect // "none")=="none" and
(.body.semantics.candidate_execution // "none")=="none" and
(.body.semantics.credential_access // "none")=="none" and
(.body.semantics.network_access // "none")=="none"
' "$decision" >/dev/null || fail "inactive decision boundary $section"
"$jq_bin" -e --arg section "$section" '
.schema_version==1 and .id==("control-policy."+$section) and
.body.policy_version=="v1" and .body.activation_state=="inactive" and
.body.fail_mode=="closed" and .body.evaluation_mode=="observation-only"
' "$policy" >/dev/null || fail "inactive policy boundary $section"
if "$jq_bin" -e '.body | has("core_contract")' "$policy" >/dev/null; then
direct_core_count=$((direct_core_count + 1))
"$jq_bin" -e --arg generation_sha "$generation_sha" \
--arg package_sha "$core_package_sha" '
.body.core_contract=={
generation_id_sha256:$generation_sha,
package_ref:{content_id:"core-contract-package.v2",
media_type:"application/vnd.ystack.core-contract+json",sha256:$package_sha},
semantic_identity:"core.contracts.v2"}
' "$policy" >/dev/null || fail "direct core contract $section"
else
case "$section" in
kill-switch|sandbox) ;;
*) fail "missing direct core contract $section" ;;
esac
fi
[ "$policy_sha" = "$("$jq_bin" -er --argjson index "$index" \
'.body.sections[$index].policy_ref.sha256' "$policy_set")" ] ||
fail "policy digest $section"
[ "$decision_sha" = "$("$jq_bin" -er --argjson index "$index" \
'.body.sections[$index].decision_ref.sha256' "$policy_set")" ] ||
fail "decision digest $section"
done
[ "$direct_core_count" -eq 4 ] || fail 'direct core contract count'
check_closure "$policy_set" || fail 'complete shipped closure'
pass 'all twelve refs and six inactive decision boundaries are exact'

mutate() {
local name=$1 filter=$2
"$jq_bin" -S -c "$filter" "$policy_set" >"$tmp/$name.json"
/usr/bin/printf '%s\n' "$tmp/$name.json"
}
expect_closure_reject() {
local name=$1 input=$2 out err
out="$tmp/$name.out"
err="$tmp/$name.err"
PATH="$bin:/usr/bin:/bin" "$validator" validate "$input" >"$out" 2>"$err" ||
fail "$name validator should accept shape"
[ ! -s "$out" ] && [ ! -s "$err" ] || fail "$name validator output"
if check_closure "$input"; then fail "$name closure accepted"; fi
pass "$name fails the exact shipped closure"
}
expect_validator_reject() {
local name=$1 input=$2 out err status=0
out="$tmp/$name.out"
err="$tmp/$name.err"
PATH="$bin:/usr/bin:/bin" "$validator" validate "$input" >"$out" 2>"$err" || status=$?
[ "$status" -ne 0 ] && [ ! -s "$out" ] &&
[ "$(/bin/cat "$err")" = E_RELATION ] || fail "$name validator closure"
if check_closure "$input"; then fail "$name closure accepted"; fi
pass "$name fails closed in the validator"
}

for index in 0 1 2 3 4 5; do
for ref_field in policy_ref decision_ref; do
name="ref-$index-$ref_field"
expect_closure_reject "$name" "$(mutate "$name" \
".body.sections[$index].$ref_field.sha256=(\"0\"*64)")"
done
done
expect_closure_reject core-generation "$(mutate core-generation \
'.body.core_contract.generation_id=("g-"+("0"*64))')"
expect_closure_reject core-package "$(mutate core-package \
'.body.core_contract.package_ref.sha256=("0"*64)')"
expect_closure_reject core-identity "$(mutate core-identity \
'.body.core_contract.semantic_identity="core.contracts.v3"')"
expect_validator_reject reordered "$(mutate reordered \
'.body.sections[0:2] |= reverse')"
expect_validator_reject duplicate "$(mutate duplicate \
'.body.sections[1]=.body.sections[0]')"
expect_validator_reject activation "$(mutate activation \
'.body.activation_state="active"')"
expect_validator_reject fail-mode "$(mutate fail-mode \
'.body.fail_mode="open"')"

for required in control/v1/control-policy-set.json \
scripts/test/control-foundation-rollup.test.sh; do
[ "$(/usr/bin/grep -Fxc "$required" "$root/ci/required-files.txt")" -eq 1 ] ||
fail "manifest $required"
done
/usr/bin/grep -Fq 'Inactive Control foundation roll-up' "$root/README.md" ||
fail 'README docs'
/usr/bin/grep -Fq 'control-foundation-rollup.test.sh' "$root/RESTORE.md" ||
fail 'RESTORE docs'
pass 'restore manifest and docs'
/usr/bin/printf 'control foundation roll-up: %s focused checks passed\n' "$passes"
2 changes: 2 additions & 0 deletions scripts/test/portable-core-schema.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ v1_activation_path_ok() {
v2_activation_path_ok() {
case "$1" in
README.md|RESTORE.md|ci/required-files.txt|\
control/v1/control-policy-set.json|\
core/v2/generation-registry.json|\
scripts/core-contract.sh|scripts/lib/profile-resolution.sh|\
scripts/test/portable-core-schema.test.sh|\
Expand Down Expand Up @@ -838,6 +839,7 @@ fi
schema_v2_expected_live_hits="$schema_test_tmp/v2-expected-live-hits"
printf '%s\n' \
ci/required-files.txt \
control/v1/control-policy-set.json \
core/v2/generation-registry.json \
"core/v2/generations/$schema_v2_generation/core-ingress.sh" \
scripts/core-contract.sh \
Expand Down