Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
72599b4
feat(contracts): expand vendor shared authorization schemas to 2.1
fraware Jul 23, 2026
be7d7d4
build: require contracts 2.1, cryptography, and REST extras
fraware Jul 23, 2026
134ed1e
feat(contracts): pin shared contracts 2.1 and harden drift checks
fraware Jul 23, 2026
df897f1
feat(trust): harden institutional trust store and strict crypto
fraware Jul 23, 2026
d4c4ba5
feat(policy): register grant issuers and issuer key material
fraware Jul 23, 2026
162efdd
feat(policy): add manifest signer and status attestation registries
fraware Jul 23, 2026
d4856ac
feat(policy): map tools, capabilities, and reviewer decisions
fraware Jul 23, 2026
2729ebd
feat(authz): add requested authorization request model
fraware Jul 23, 2026
09ef2ed
feat(authz): gate grants against authorization manifest schema
fraware Jul 23, 2026
08775f5
test(helpers): add institutional grant fixture builders
fraware Jul 23, 2026
46af4ad
feat(verifier): harden scope grant verification lifecycle
fraware Jul 23, 2026
2bf77b7
feat(negotiation): tighten scope contract and peer checks
fraware Jul 23, 2026
da223f9
feat(lifecycle): codify grant status and forgery semantics
fraware Jul 23, 2026
53dc1e5
feat(evidence): keep admissibility evidence grant-independent
fraware Jul 23, 2026
8a452b6
feat(review): wire grant checks into review and gate paths
fraware Jul 23, 2026
c0df720
feat(policy): strengthen effective policy integrity and load path
fraware Jul 23, 2026
0607c37
feat(compat): refresh SCOPE compatibility and sibling repo pins
fraware Jul 23, 2026
28c49e5
feat(rest): harden institutional identity verification
fraware Jul 23, 2026
edc64e8
feat(rest): add institutional PostgreSQL persistence mode
fraware Jul 23, 2026
c311b1b
feat(rest): enforce institutional auth on REST server paths
fraware Jul 23, 2026
e745493
feat(release): expand release pins for institutional gates
fraware Jul 23, 2026
8ee2edb
feat(release): add wheel smoke and release evidence reporting
fraware Jul 23, 2026
2b19b34
ci: expand CI and release-gate for institutional 1.1 checks
fraware Jul 23, 2026
c7ced71
docs: document 1.1 release, deployment, and sibling integration
fraware Jul 23, 2026
1517ed3
feat(evals): update empirical protocol for institutional impact
fraware Jul 23, 2026
698ed95
test(acceptance): cover integrated protocol and trust domains
fraware Jul 23, 2026
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
16 changes: 11 additions & 5 deletions .github/SUPPLY_CHAIN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@ Workflows under `.github/workflows/` pin third-party GitHub Actions to full comm
| CodeQL | `.github/workflows/codeql.yml` (Python) |
| SBOM | CycloneDX JSON attached on package/tag builds when tooling available |
| Wheel build + twine check | `package` job |
| Wheel install smoke | Install built wheel into clean venv and import `akta` |
| Reproducibility comparison | Optional second wheel build hash compare when enabled |
| Package provenance hooks | GitHub Attestations / `actions/attest-build-provenance` on tags when available |
## Supply-chain / release evidence (WS14)

| Control | Placement |
|---------|-----------|
| Full wheel smoke | `python -m akta.wheel_smoke` after clean wheel install (schemas, grant auth, status, containment, evidence, PF/PCS) |
| Reproducibility | Second build under `SOURCE_DATE_EPOCH`; **fails** unless digests match or `docs/reproducibility_normalization.md` lists an allowed token |
| Sibling matrix on tags | `.github/workflows/release-gate.yml` requires full PF/PCS/SCOPE/VSA/Memory matrix on `v*` |
| Release evidence report | `scripts/build_release_evidence_report.py` → `dist/release_evidence.json` |
| VSA pin | `903d834f…` (`v0.7.2`); missing checkout / SHA mismatch remain fail-closed |

## Sibling pins (P1-A)

Institutional release pins live in `policy/release_pins.yaml` and are recorded in
`scripts/verify_v1_release.py --institutional` reports. Missing siblings stay
fail-closed placeholders — never silently optionalized under institutional_release.
`scripts/verify_v1_release.py --institutional` reports. Missing checkouts or SHA
mismatches stay fail-closed — never silently optionalized under institutional_release.
124 changes: 101 additions & 23 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: pip install -e ".[dev,security]"
- name: Install shared contracts then AKTA
run: |
pip install ./vendor/scientific-authorization-contracts
pip install -e ".[dev,security]"

- name: Shared contract drift gate
run: python scripts/assert_shared_contract_drift.py
Expand Down Expand Up @@ -78,12 +80,17 @@ jobs:
deps = list(data["project"]["dependencies"])
for extra in ("dev", "security"):
deps.extend(data["project"].get("optional-dependencies", {}).get(extra, []))
# Vendor-local package; not on public indexes yet.
deps = [
d for d in deps
if not str(d).startswith("scientific-authorization-contracts")
]
pathlib.Path("requirements-audit.txt").write_text("\n".join(deps) + "\n", encoding="utf-8")
PY
pip-audit -r requirements-audit.txt --progress-spinner off

- name: Grant forgery lifecycle tests
run: pytest tests/test_grant_forgery_lifecycle.py tests/test_institutional_trust_store.py -v
run: pytest tests/test_grant_forgery_lifecycle.py tests/test_institutional_trust_store.py tests/test_strict_mode_crypto.py tests/test_trust_domains.py -v

- name: Run pytest
run: pytest tests/ skills/akta-scientific-action-admissibility/tests/ -v
Expand Down Expand Up @@ -153,18 +160,29 @@ jobs:
with:
python-version: "3.12"
- name: Install build tooling
run: pip install -e ".[dev,security]"
run: |
pip install ./vendor/scientific-authorization-contracts
pip install -e ".[dev,security]"
- name: Shared contract drift gate
run: python scripts/assert_shared_contract_drift.py
- name: Build wheel and sdist
env:
SOURCE_DATE_EPOCH: "1700000000"
run: python -m build
- name: Twine check
run: twine check dist/*
- name: Wheel install smoke
- name: Wheel install smoke (full institutional path)
env:
SOURCE_DATE_EPOCH: "1700000000"
run: |
python -m venv /tmp/akta-wheel-smoke
# Contracts first (no public index), then AKTA wheel in a clean venv.
/tmp/akta-wheel-smoke/bin/pip install ./vendor/scientific-authorization-contracts
/tmp/akta-wheel-smoke/bin/pip install dist/*.whl
/tmp/akta-wheel-smoke/bin/python -c "import akta; from akta.trust_store import resolve_trust_store; print('ok', akta.__name__)"
# Policy/overlays are package data for gate path; bind from checkout for smoke.
cp -a policy overlays /tmp/akta-wheel-smoke/
cd /tmp/akta-wheel-smoke
./bin/python -m akta.wheel_smoke
- name: SBOM (CycloneDX when available)
run: |
pip install cyclonedx-bom >/dev/null 2>&1 || true
Expand All @@ -188,38 +206,70 @@ jobs:
print("wrote stub SBOM")
PY
fi
- name: Reproducibility comparison (second build hash)
- name: Reproducibility comparison (fail-closed unless documented)
env:
SOURCE_DATE_EPOCH: "1700000000"
run: |
python -m build -o dist-repro
python - <<'PY'
import hashlib, pathlib, sys
import hashlib, json, pathlib, sys
def digest(pattern):
paths = sorted(pathlib.Path('.').glob(pattern))
h = hashlib.sha256()
wheels = []
for p in paths:
if p.suffix == '.whl':
h.update(p.read_bytes())
return h.hexdigest(), [str(p) for p in paths if p.suffix == '.whl']
wheels.append(str(p))
return h.hexdigest(), wheels
a, pa = digest('dist/*.whl')
b, pb = digest('dist-repro/*.whl')
print({'dist': pa, 'dist_repro': pb, 'sha256_dist': a, 'sha256_repro': b, 'match': a == b})
# Record comparison; do not fail CI on non-bit-identical wheels (setuptools metadata).
match = a == b
norm_doc = pathlib.Path('docs/reproducibility_normalization.md')
norm_text = norm_doc.read_text(encoding='utf-8') if norm_doc.is_file() else ''
# Only tokens listed under "## Active exceptions" count (not the vocabulary table).
active = ''
if '## Active exceptions' in norm_text:
active = norm_text.split('## Active exceptions', 1)[1]
if '##' in active:
active = active.split('##', 1)[0]
allowed_tokens = ('WHEEL_METADATA_TIMESTAMP', 'PLATFORM_TAG_DRIFT')
documented = any(tok in active for tok in allowed_tokens) and 'None.' not in active.strip().splitlines()[:5]
# Treat explicit "None." as no active exception.
if active.strip().startswith('None.') or active.strip() == 'None':
documented = False
payload = {
'sha256_dist': a,
'sha256_repro': b,
'match': match,
'dist': pa,
'dist_repro': pb,
'source_date_epoch': '1700000000',
'normalization_doc': 'docs/reproducibility_normalization.md',
'documented_exception': (not match) and documented,
}
pathlib.Path('dist').mkdir(exist_ok=True)
pathlib.Path('dist/reproducibility.json').write_text(
__import__('json').dumps({'sha256_dist': a, 'sha256_repro': b, 'match': a == b}, indent=2),
encoding='utf-8',
json.dumps(payload, indent=2), encoding='utf-8'
)
print(payload)
if not match and not documented:
print(
'FAIL: release artifacts differ and no active exception token is '
'listed under "## Active exceptions" in docs/reproducibility_normalization.md',
file=sys.stderr,
)
sys.exit(1)
if not match and documented:
print(
'WARN: artifacts differ; accepted only because an active '
'normalization exception token is listed'
)
PY
- name: Upload package artifacts
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: akta-packages
path: |
dist/
dist-repro/
- name: pip-audit (fail-closed on declared deps)
run: |
python - <<'PY'
import pathlib
import pathlib, json
try:
import tomllib
except ModuleNotFoundError:
Expand All @@ -228,9 +278,35 @@ jobs:
deps = list(data["project"]["dependencies"])
for extra in ("dev", "security"):
deps.extend(data["project"].get("optional-dependencies", {}).get(extra, []))
# Vendor-local package; not on public indexes yet.
deps = [
d for d in deps
if not str(d).startswith("scientific-authorization-contracts")
]
pathlib.Path("requirements-audit.txt").write_text("\n".join(deps) + "\n", encoding="utf-8")
PY
pip-audit -r requirements-audit.txt --progress-spinner off
mkdir -p dist
pip-audit -r requirements-audit.txt --progress-spinner off --format json -o dist/pip-audit.json || pip-audit -r requirements-audit.txt --progress-spinner off
- name: Release evidence report
run: |
python scripts/build_release_evidence_report.py --out dist/release_evidence.json
python - <<'PY'
import json, pathlib, re
report = json.loads(pathlib.Path('dist/release_evidence.json').read_text(encoding='utf-8'))
vsa = report.get('vsa_pin') or {}
commit = str(vsa.get('commit') or '')
assert vsa.get('pinned') is True, f'VSA must be pinned in release evidence, got {vsa!r}'
assert vsa.get('fail_closed_placeholder') is not True
assert re.fullmatch(r'[0-9a-f]{40}', commit), f'bad VSA commit {commit!r}'
print(f"release evidence ok; VSA pinned {commit} tag={vsa.get('tag')}")
PY
- name: Upload package artifacts
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: akta-packages
path: |
dist/
dist-repro/

cross-repo-pf-pcs:
runs-on: ubuntu-latest
Expand All @@ -241,7 +317,9 @@ jobs:
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -e ".[dev,security]"
run: |
pip install ./vendor/scientific-authorization-contracts
pip install -e ".[dev,security]"
- name: Cross-repo PF-Core validation
if: ${{ vars.PF_CORE_REPO_PATH != '' }}
env:
Expand Down
106 changes: 93 additions & 13 deletions .github/workflows/release-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ jobs:
vsa_repo_url: ${{ secrets.VSA_REPO_URL || vars.VSA_PUBLIC_REPO_URL }}
memory_repo_url: ${{ secrets.MEMORY_REPO_URL || vars.MEMORY_PUBLIC_REPO_URL }}
- name: Install dependencies
run: pip install -e ".[dev,security]"
run: |
pip install ./vendor/scientific-authorization-contracts
pip install -e ".[dev,security]"
- name: Require SCOPE sibling path
run: |
if [ -z "${SCOPE_REPO_PATH:-}" ]; then
Expand Down Expand Up @@ -111,24 +113,80 @@ jobs:
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Resolve sibling clone URLs (mandatory public fallbacks on tags)
id: sibling_urls
shell: bash
run: |
set -euo pipefail
is_tag=0
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
is_tag=1
fi
echo "is_release_tag=${is_tag}" >> "$GITHUB_OUTPUT"

pick() {
local secret="$1" var="$2" public="$3"
if [ -n "${secret}" ]; then echo "${secret}"; return; fi
if [ -n "${var}" ]; then echo "${var}"; return; fi
if [ "${is_tag}" = "1" ]; then echo "${public}"; return; fi
echo ""
}

echo "pf_core_repo_url=$(pick '${{ secrets.PF_CORE_REPO_URL }}' '${{ vars.PF_CORE_PUBLIC_REPO_URL }}' 'https://github.com/SentinelOps-CI/provability-fabric-core.git')" >> "$GITHUB_OUTPUT"
echo "pcs_core_repo_url=$(pick '${{ secrets.PCS_CORE_REPO_URL }}' '${{ vars.PCS_CORE_PUBLIC_REPO_URL }}' 'https://github.com/SentinelOps-CI/pcs-core.git')" >> "$GITHUB_OUTPUT"
echo "pcs_bench_repo_url=$(pick '${{ secrets.PCS_BENCH_REPO_URL }}' '${{ vars.PCS_BENCH_PUBLIC_REPO_URL }}' 'https://github.com/fraware/pcs-bench.git')" >> "$GITHUB_OUTPUT"
echo "vsa_repo_url=$(pick '${{ secrets.VSA_REPO_URL }}' '${{ vars.VSA_PUBLIC_REPO_URL }}' 'https://github.com/fraware/verified-science-agent.git')" >> "$GITHUB_OUTPUT"
echo "memory_repo_url=$(pick '${{ secrets.MEMORY_REPO_URL }}' '${{ vars.MEMORY_PUBLIC_REPO_URL }}' 'https://github.com/fraware/scientific-memory.git')" >> "$GITHUB_OUTPUT"
- name: Clone trust-stack siblings
uses: ./.github/actions/clone-siblings
with:
workspace: ${{ github.workspace }}
scope_repo_url: ${{ secrets.SCOPE_REPO_URL || vars.SCOPE_PUBLIC_REPO_URL || 'https://github.com/fraware/SCOPE.git' }}
pf_core_repo_url: ${{ secrets.PF_CORE_REPO_URL || vars.PF_CORE_PUBLIC_REPO_URL }}
pcs_core_repo_url: ${{ secrets.PCS_CORE_REPO_URL || vars.PCS_CORE_PUBLIC_REPO_URL }}
pcs_bench_repo_url: ${{ secrets.PCS_BENCH_REPO_URL || vars.PCS_BENCH_PUBLIC_REPO_URL }}
vsa_repo_url: ${{ secrets.VSA_REPO_URL || vars.VSA_PUBLIC_REPO_URL }}
memory_repo_url: ${{ secrets.MEMORY_REPO_URL || vars.MEMORY_PUBLIC_REPO_URL }}
pf_core_repo_url: ${{ steps.sibling_urls.outputs.pf_core_repo_url }}
pcs_core_repo_url: ${{ steps.sibling_urls.outputs.pcs_core_repo_url }}
pcs_bench_repo_url: ${{ steps.sibling_urls.outputs.pcs_bench_repo_url }}
vsa_repo_url: ${{ steps.sibling_urls.outputs.vsa_repo_url }}
memory_repo_url: ${{ steps.sibling_urls.outputs.memory_repo_url }}
- name: Install dependencies
run: pip install -e ".[dev,security]"
run: |
pip install ./vendor/scientific-authorization-contracts
pip install -e ".[dev,security]"
- name: Require full sibling matrix on release tags
if: startsWith(github.ref, 'refs/tags/v')
run: |
set -euo pipefail
missing=()
for var in SCOPE_REPO_PATH PF_CORE_REPO_PATH PCS_CORE_REPO_PATH PCS_BENCH_REPO_PATH VSA_REPO_PATH MEMORY_REPO_PATH; do
if [ -z "${!var:-}" ]; then
missing+=("$var")
fi
done
if [ "${#missing[@]}" -ne 0 ]; then
echo "FAIL: release tag requires full sibling matrix; missing: ${missing[*]}"
exit 1
fi
echo "Full sibling matrix present for release tag"
python - <<'PY'
from akta.release_pins import load_release_pins
pins = load_release_pins()
vsa = (pins.get("components") or {}).get("VSA") or {}
commit = str(vsa.get("commit") or "")
assert vsa.get("status") == "pinned", f"VSA status must be pinned, got {vsa.get('status')!r}"
assert len(commit) == 40 and all(c in "0123456789abcdef" for c in commit), (
f"VSA commit must be a real 40-char SHA, got {commit!r}"
)
assert "PLACEHOLDER" not in commit.upper() and "UNAVAILABLE" not in commit.upper()
print(f"VSA pin ok: {commit} tag={vsa.get('tag')}")
PY
- name: PF runtime proof
env:
PF_CORE_REPO_PATH: ${{ env.PF_CORE_REPO_PATH || vars.PF_CORE_REPO_PATH }}
run: |
if [ -n "$PF_CORE_REPO_PATH" ]; then
if [ -n "${PF_CORE_REPO_PATH:-}" ]; then
python scripts/demo_pf_runtime_proof.py
elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "FAIL: PF_CORE_REPO_PATH required on release tags"
exit 1
elif [ -n "${{ vars.PF_CORE_REPO_PATH }}" ]; then
echo "FAIL: PF_CORE_REPO_PATH var set but clone/path missing"
exit 1
Expand All @@ -139,8 +197,11 @@ jobs:
env:
PCS_CORE_REPO_PATH: ${{ env.PCS_CORE_REPO_PATH || vars.PCS_CORE_REPO_PATH }}
run: |
if [ -n "$PCS_CORE_REPO_PATH" ]; then
if [ -n "${PCS_CORE_REPO_PATH:-}" ]; then
pytest tests/contracts/test_pcs_core_live_ingest.py -v -m integration
elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "FAIL: PCS_CORE_REPO_PATH required on release tags"
exit 1
elif [ -n "${{ vars.PCS_CORE_REPO_PATH }}" ]; then
echo "FAIL: PCS_CORE_REPO_PATH var set but clone/path missing"
exit 1
Expand All @@ -151,8 +212,11 @@ jobs:
env:
PCS_BENCH_REPO_PATH: ${{ env.PCS_BENCH_REPO_PATH || vars.PCS_BENCH_REPO_PATH }}
run: |
if [ -n "$PCS_BENCH_REPO_PATH" ]; then
if [ -n "${PCS_BENCH_REPO_PATH:-}" ]; then
python -m adapters.pcs_bench.external_harness
elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "FAIL: PCS_BENCH_REPO_PATH required on release tags"
exit 1
elif [ -n "${{ vars.PCS_BENCH_REPO_PATH }}" ]; then
echo "FAIL: PCS_BENCH_REPO_PATH var set but clone/path missing"
exit 1
Expand All @@ -163,10 +227,10 @@ jobs:
env:
VSA_REPO_PATH: ${{ env.VSA_REPO_PATH || vars.VSA_REPO_PATH }}
run: |
if [ -n "$VSA_REPO_PATH" ]; then
if [ -n "${VSA_REPO_PATH:-}" ]; then
pytest tests/contracts/test_vsa_live_contract.py -v -m integration
python -c "
import json, os
import json
from pathlib import Path
from tests.contracts.cross_repo_helpers import validate_vsa_report_live
pilot = Path('dist/pilot_bundle/00_vsa_report.json')
Expand All @@ -175,6 +239,9 @@ jobs:
skip = validate_vsa_report_live(report)
assert skip is None, skip
"
elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "FAIL: VSA_REPO_PATH required on release tags (clone for live contract + SHA match)"
exit 1
elif [ -n "${{ vars.VSA_REPO_PATH }}" ]; then
echo "FAIL: VSA_REPO_PATH var set but clone/path missing"
exit 1
Expand All @@ -185,14 +252,27 @@ jobs:
env:
MEMORY_REPO_PATH: ${{ env.MEMORY_REPO_PATH || vars.MEMORY_REPO_PATH }}
run: |
if [ -n "$MEMORY_REPO_PATH" ]; then
if [ -n "${MEMORY_REPO_PATH:-}" ]; then
pytest tests/contracts/test_scientific_memory_roundtrip.py -v -m integration
elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "FAIL: MEMORY_REPO_PATH required on release tags"
exit 1
elif [ -n "${{ vars.MEMORY_REPO_PATH }}" ]; then
echo "FAIL: MEMORY_REPO_PATH var set but clone/path missing"
exit 1
else
echo "MEMORY_REPO_PATH not configured; skipping memory round-trip"
fi
- name: Release evidence (sibling matrix)
if: startsWith(github.ref, 'refs/tags/v')
run: |
python scripts/build_release_evidence_report.py --out dist/release_evidence.json
- name: Upload release evidence
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: release-evidence
path: dist/release_evidence.json

eval-bench-v1:
runs-on: ubuntu-latest
Expand Down
Loading
Loading