access-engine/tools/export_decisionpep_adapter.py

59 lines
2.9 KiB
Python
Raw Normal View History

"""Export the Go 1.24 consumer slice from the producer's single source tree."""
from pathlib import Path
import argparse
import hashlib
import json
ROOT = Path(__file__).resolve().parent.parent
DESTINATION = ROOT / 'adapters/go/decisionpep'
FILES = ['LICENSE', 'pkg/api/canonical.go', 'pkg/api/caring.go',
'pkg/api/resource_manifest.go', 'internal/sign/sign.go',
'pkg/decisionpep/client.go', 'pkg/decisionpep/client_test.go',
'testsupport/signfixture/sign.go']
BASELINE = {
'pkg/api/canonical.go': 'a122a2e8cd524333b13c5939c7a3685e41efbe47497a64e0c7297c92b7f10d19',
'pkg/api/caring.go': '1907156f0f889e7b9e9c14970cf7a86a20d00478a496efaf92c7231f27fec5e3',
'pkg/api/resource_manifest.go': 'f0fa4080287d389ed48c2b1d6af96cc62e57ef72c902333f677f964420be133f',
'internal/sign/sign.go': '0df9515922e90775ebbfac798361dcafb20da8a4213796b44e246b8a92046cde',
'LICENSE': 'ff413f361a3b3bf44cf50f110fbcc4837064d57eefbcef89df2b43997c6262b6',
}
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--check', action='store_true')
args = parser.parse_args()
output = {name: (ROOT / name).read_bytes() for name in FILES}
for name, digest in BASELINE.items():
if hashlib.sha256(output[name]).hexdigest() != digest:
raise SystemExit('Producer API/signature baseline changed; review the export contract before advancing it')
output['go.mod'] = b'module github.com/netkingdom/access-engine\n\ngo 1.24\n'
metadata = {
'upstream': 'github.com/netkingdom/access-engine',
'commit': 'd328a2601095686f74376d87791bff01e2a3a2a3',
'exact_unchanged_files': BASELINE,
'module': 'Standalone Go1.24 source slice with original module/import identity; no canonical/schema/signature modifications',
'new_code': ['pkg/decisionpep/client.go'],
'fixture_code': ['testsupport/signfixture/sign.go'],
'source_of_truth': 'repository root; generated with tools/export_decisionpep_adapter.py',
'exported_file_sha256': {name: hashlib.sha256(raw).hexdigest() for name, raw in sorted(output.items())},
}
output['producer-source.json'] = (json.dumps(metadata, indent=2) + '\n').encode()
actual = {str(item.relative_to(DESTINATION)) for item in DESTINATION.rglob('*') if item.is_file()}
if actual - set(output):
raise SystemExit('Unexpected files in the generated consumer slice')
if args.check:
drift = [name for name, raw in output.items() if not (DESTINATION / name).is_file() or (DESTINATION / name).read_bytes() != raw]
if drift:
raise SystemExit('Generated consumer slice differs: ' + ', '.join(drift))
else:
for name, raw in output.items():
path = DESTINATION / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(raw)
print(json.dumps({'status': 'verified' if args.check else 'exported', 'files': len(output)}))
if __name__ == '__main__':
main()