Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
242 commits
Select commit Hold shift + click to select a range
c20661d
docs: spec for persistent drive leases with fencing and restart recov…
Amantux Oct 9, 2026
6276db4
feat(catalog): drive_leases table and repository lease API
Amantux Oct 9, 2026
605978e
feat(jobs): DriveScheduler over a LeaseStore, with fencing verify/hea…
Amantux Oct 9, 2026
6502793
feat(jobs): fence sharded archive on drive leases (partial slice of s…
Amantux Oct 9, 2026
f364623
feat(jobs): bind every scheduler to the catalog lease store; fence bl…
Amantux Oct 9, 2026
b4c32e7
feat(jobs): recover_after_restart reconciles jobs and drive leases (r…
Amantux Oct 9, 2026
4e67682
feat(jobs): run restart recovery in create_context and expose it at G…
Amantux Oct 9, 2026
de4f999
docs: architecture section for drive leases/recovery; record implemen…
Amantux Oct 9, 2026
096a2bf
fix(catalog): run lease operations on their own session, not the shar…
Amantux Oct 9, 2026
e2443f2
fix(recovery): act only on expired leases — never fail a job another …
Amantux Oct 9, 2026
5f2ba33
fix(jobs): fenced-out jobs leave the drive alone; background heartbea…
Amantux Oct 9, 2026
47dc550
docs(spec): record the review-driven recovery scoping and fenced-out …
Amantux Oct 9, 2026
da84f5b
feat(domain): add STAGING and VERIFYING file-instance states
Amantux Oct 9, 2026
7ff9ba9
ci(operability): pin actions to full commit SHAs
Amantux Oct 9, 2026
9432278
feat(domain): model placement, striping and protection as separate axes
Amantux Oct 9, 2026
daff4da
ci: add nightly/manual NAS protocol rig workflow
Amantux Oct 9, 2026
de01abe
docs: describe NAS protocol test rig
Amantux Oct 9, 2026
58d0f04
docs: rewrite tech-debt with verified state; document CI lanes
Amantux Oct 9, 2026
ef6bc31
feat(nas): render full smb.conf and Ganesha config from NasShare records
Amantux Oct 9, 2026
870e836
feat(deploy): read-only appliance postcheck and digest rollback
Amantux Oct 9, 2026
64bb29e
feat(fuse): byte-budget LRU cache and batching Hydrator over the rest…
Amantux Oct 9, 2026
331adbf
feat(fuse): state xattr, open-handle refcount, blocking/EAGAIN hydrat…
Amantux Oct 9, 2026
0babc3a
ci: pin actions to SHAs and scope permissions per job
Amantux Oct 9, 2026
0ff26ed
ci: consolidate emulator boot/test into reusable workflow (SHA-pinned)
Amantux Oct 9, 2026
045d3c1
ci: add workflow-lint (actionlint, zizmor, shellcheck, yamllint)
Amantux Oct 9, 2026
e5b444e
feat(nas): protocol gateway on_open/on_read_range/on_close/on_evict o…
Amantux Oct 9, 2026
62deb3f
feat(nas): manifest v2 with commit marker written last and generation…
Amantux Oct 9, 2026
79f4e6e
ci(release): build-once digest pipeline with SBOM, scan, signing and …
Amantux Oct 9, 2026
82d6688
docs: release runbook and digest-pinned deployment examples
Amantux Oct 9, 2026
ef5a7be
merge: fleet/release-pipeline (roadmap item 24)
Amantux Oct 9, 2026
bb6aeff
ci(hardware): add rig-guarded read-only and destructive i3 lanes; reh…
Amantux Oct 9, 2026
8e23d57
docs(hardware): runbook for self-hosted i3 lanes; gate write paths on…
Amantux Oct 9, 2026
bf072c6
feat(nas): cartridge lifecycle state machine with typed invalid trans…
Amantux Oct 9, 2026
99e2c6e
feat(nas): LTO compat matrix, foreign-media guard and reservations in…
Amantux Oct 9, 2026
5d5e98a
feat(nas): scratch, fragmentation, reservation, replication, span, ex…
Amantux Oct 9, 2026
2e4eb31
docs(nas): document tape-native planning models
Amantux Oct 9, 2026
58827b3
fix(fuse): never budget-evict the entry just stored for a waiting reader
Amantux Oct 9, 2026
d465a5e
test(fuse): data-plane integration tests (hydrate, tickets, timeout, …
Amantux Oct 9, 2026
6190584
build: install fuse3/libfuse3 so the FUSE mount works in the shipped …
Amantux Oct 9, 2026
a06aeb0
test(i3): Clock abstraction and fault-shaped timing profiles
Amantux Oct 9, 2026
f22c4a8
docs(fuse): describe the five data-plane layers honestly; correct the…
Amantux Oct 9, 2026
4c75df3
test: register contract marker and make test-contract target
Amantux Oct 9, 2026
39a27f8
test: backend contract suite across sim, in-process emulator and real…
Amantux Oct 9, 2026
ecf2052
docs: document the backend contract suite and new-backend rule
Amantux Oct 9, 2026
1dc34c0
docs: protection axis table and commit-marker recovery rules
Amantux Oct 9, 2026
f790ba5
feat(nas): rebuild skips uncommitted generations and reports missing …
Amantux Oct 9, 2026
a9ccc50
merge: fleet/contract-suite (roadmap item 5)
Amantux Oct 9, 2026
7feed22
feat(hardware): resolve_tape_by_id maps a drive serial to its /dev/ta…
Amantux Oct 9, 2026
5492fcc
feat(tools): sacrificial-barcode allowlist gate and inventory/drive s…
Amantux Oct 9, 2026
7f8389f
test(hardware): read-only rig suite, drive-identity bridge, and AST g…
Amantux Oct 9, 2026
2105632
ci(hardware): pass appliance config to rig jobs and fail preflight in…
Amantux Oct 9, 2026
46d5a74
fix(scalar_http): refuse unload while the host-side LTFS state is mou…
Amantux Oct 9, 2026
b6c71b6
merge: fleet/tape-manifest (roadmap items 9, 10)
Amantux Oct 9, 2026
8d3cded
feat(catalog): job journal and staged-instance lifecycle methods
Amantux Oct 9, 2026
3389085
test(integration): rendezvous all three lease holders before assertin…
Amantux Oct 9, 2026
24dbb32
fix(nas): Ganesha config disables NLM/RQUOTA for the NFSv4-only export
Amantux Oct 9, 2026
3278209
feat(deploy): containerised Samba + NFS-Ganesha protocol rig with hyd…
Amantux Oct 9, 2026
286e1d8
test(e2e): SMB/NFS protocol scenarios, protocols marker, make targets
Amantux Oct 9, 2026
bb1aee3
merge: fleet/nas-models (roadmap item 20)
Amantux Oct 9, 2026
42bfac4
feat(aml-auth): session cap, strict 412, XML login negotiation, Retry…
Amantux Oct 9, 2026
8bc5fd7
docs(compat): inferred auth cases, iblade-rev-a scaffold, auth contra…
Amantux Oct 9, 2026
367d39c
test(hardware): format LTFS test tapes via FormatService dry-run + to…
Amantux Oct 9, 2026
cd361fb
test(hardware): enforce read-only at runtime (HTTP + argv allowlists)…
Amantux Oct 9, 2026
5351b3e
feat(tools): junit skip gate, normalized allowlist output, snapshot r…
Amantux Oct 9, 2026
06b740d
ci(hardware): gate rig lanes on junit (no skip-as-pass), job-level ri…
Amantux Oct 9, 2026
746742b
merge: fleet/jobs-atomic
Amantux Oct 9, 2026
de4d69b
merge: fleet/aml-auth
Amantux Oct 9, 2026
fe78300
merge: fleet/hardware-lane
Amantux Oct 9, 2026
51e19e3
fix(nas): render Ganesha Clients unquoted so EXPORTs load
Amantux Oct 9, 2026
68a5d40
fix(e2e): stage guest-writable .ob-control/offline for recall requests
Amantux Oct 9, 2026
135a92e
test(e2e): assert smbcacls owner/group/everyone ACEs for mode 0640
Amantux Oct 9, 2026
1cce6d3
docs(deploy): note the catalog has no on-disk OFFLINE_ON_TAPE form
Amantux Oct 9, 2026
6e9d958
sharded_archive: stage instances, one bulk commit, journal physical_s…
Amantux Oct 9, 2026
a128e02
feat(jobs): take non-sharded archive/restore drives through DriveSche…
Amantux Oct 9, 2026
579628e
feat(api,cli): pass the shared lease-store scheduler to run_archive_j…
Amantux Oct 9, 2026
ddaed9d
fix(api): AML error envelope keeps exception headers and covers unhan…
Amantux Oct 9, 2026
a96533c
sharded_restore: journal physical_state_unknown instead of suppressin…
Amantux Oct 9, 2026
02cc807
test(jobs): lease contention and stale-lease fencing for non-sharded …
Amantux Oct 9, 2026
c94cd6c
test: staged sharded archive never archives on lane failure; cleanup …
Amantux Oct 9, 2026
e1c030d
merge: fleet/jobs-leases (leases for the non-sharded paths)
Amantux Oct 9, 2026
ea2621d
merge: fleet/jobs-sharded (staged commit, no suppressed cleanup errors)
Amantux Oct 9, 2026
a4245bc
fix(nas): gateway on_open pins every open so on_close cannot drop ano…
Amantux Oct 9, 2026
0e3d145
fix(jobs): never attempt an unload after a failed unmount; curate rou…
Amantux Oct 9, 2026
1845198
feat(rebuild): structured uncommitted_generations and missing_sibling…
Amantux Oct 9, 2026
e61a029
test(jobs): a drive whose unmount failed is never asked to unload
Amantux Oct 9, 2026
4b24933
feat(nas): NasPool.protection explicit policy; protection_from_pool p…
Amantux Oct 9, 2026
5750f09
fix(fuse): hydration workers complete tickets on any engine error
Amantux Oct 9, 2026
4d3782d
fix(fuse): resume() re-reads the job each poll and stops at a deadline
Amantux Oct 9, 2026
fc08942
feat(rebuild): recover dataset protection policy into nas_datasets.pr…
Amantux Oct 9, 2026
2df1d67
feat(recovery): report staged instances and stale pending jobs
Amantux Oct 9, 2026
4c213b9
test(compat): raw body, content_type, repeat and expected.headers in …
Amantux Oct 9, 2026
f91518e
docs: record phase-2 recovery report fields and staged-commit follow-up
Amantux Oct 9, 2026
e4a3fce
test(e2e): rewrite asserts in protocol scenarios so failures show values
Amantux Oct 9, 2026
966d399
fix(nas): disable oplocks/SMB2 leases so SMB clients see hydrated files
Amantux Oct 9, 2026
bd9dffe
fix(e2e): tolerate .req vanishing mid-create under concurrent SMB rec…
Amantux Oct 9, 2026
9a1f977
fix(fuse): waiters pin the cache entry so a batch cannot evict it unread
Amantux Oct 9, 2026
67a7440
docs: scope phase-2 follow-up to what this branch carries
Amantux Oct 9, 2026
8d677c0
docs(nas): correct protocol rig mounts/ports and record SMB caching s…
Amantux Oct 9, 2026
c81e74e
fix(fuse): shutdown never strands a racing ticket; one overall wait d…
Amantux Oct 9, 2026
a98947e
merge: fleet/jobs-recovery (recovery report: staged instances, stale …
Amantux Oct 9, 2026
d9894e5
fix(recovery): keep live leases whose owner is still pending
Amantux Oct 9, 2026
cc35a6e
fix(fuse): delete the staging copy after a verified store or checksum…
Amantux Oct 9, 2026
b18c7b6
ci: add changed-path ownership check (tools/ci_ownership.py)
Amantux Oct 9, 2026
22d6f41
ci: SHA-pin ci.yml, add ownership job to ci-gate, drop stale advisory…
Amantux Oct 9, 2026
953b18e
test: add stress/fuzz/rebuild/mutation markers, enable --strict-markers
Amantux Oct 9, 2026
d8afb6e
ci: add mutmut mutation lane with survivor ratchet baseline
Amantux Oct 9, 2026
823d8e1
ci: add nightly slow/stress/fuzz/rebuild/mutation lanes
Amantux Oct 9, 2026
026b280
merge: fleet/nas-protocols (roadmap item 19)
Amantux Oct 9, 2026
7a6b86f
merge: fleet/ci-hardening (roadmap items 11-17)
Amantux Oct 9, 2026
0744515
ci: persist-credentials=false on every checkout; zizmor/actionlint/ya…
Amantux Oct 9, 2026
95919e6
merge: fleet/manifest-wiring (rebuild policy persistence, compat harn…
Amantux Oct 9, 2026
57a9eed
merge: fleet/fuse-plane (roadmap item 21)
Amantux Oct 9, 2026
5fb1d29
fix(verify): skip STAGING/VERIFYING instances — recovery owns them, n…
Amantux Oct 9, 2026
c25258e
fuse: hydrator worker threads use a private catalog Session
Amantux Oct 9, 2026
94bee9b
fuse: `fuse mount --hydrate` builds the batched Hydrator data plane
Amantux Oct 9, 2026
aea8421
docs(fuse): CLI data plane and per-thread sessions are now real
Amantux Oct 9, 2026
6a57f3a
test: own the contract suite and protocol render test; bridge test ex…
Amantux Oct 9, 2026
caa6ae6
ci(emulator-gates): keep the contract-pinned validation command as an…
Amantux Oct 9, 2026
7df5cb5
docs(roadmap): verified per-item status after the 2026-10-09 fleet in…
Amantux Oct 9, 2026
91359c6
merge: fleet/fuse-wiring (per-thread sessions, CLI data plane)
Amantux Oct 9, 2026
e107415
feat(fuse): OPENBLADE_FUSE_CACHE_MAX_BYTES bounds the hydration cache…
Amantux Oct 9, 2026
3f8a751
feat(restore): run_restore_batch -- one lease/load/mount/unload per s…
Amantux Oct 9, 2026
f089e77
feat(fuse): JobRestoreEngine submits one restore job per tape batch
Amantux Oct 9, 2026
a218709
docs(fuse): one restore job (one tape load) per hydration batch
Amantux Oct 9, 2026
96c3b33
chore: replace deprecated datetime.utcnow() with domain.clock.naive_u…
Amantux Oct 9, 2026
6e58d5b
fix(safety): unload gates for real hardware and across processes
Amantux Oct 9, 2026
1434785
fix(jobs): ArchiveService schedules through the catalog lease store
Amantux Oct 9, 2026
f41bf6b
merge: fleet/fuse-batch (one tape load per hydration batch)
Amantux Oct 9, 2026
84a41ef
fix(jobs): RestoreService schedules through the catalog lease store (…
Amantux Oct 9, 2026
e78f155
fix(jobs): curated physical-state error text; failure-path journaling…
Amantux Oct 9, 2026
e098d1c
chore: finish the utcnow sweep (column defaults, gateway); refresh te…
Amantux Oct 9, 2026
7175adc
fix(nas): hash on-tape bytes for commit markers, not a model re-dump
Amantux Oct 9, 2026
312f191
fix(fuse): restarted hydrator finds and resumes batch restore jobs
Amantux Oct 9, 2026
0bc5e58
fix(nas): gateway on_open returns a handle token; on_close releases o…
Amantux Oct 9, 2026
9a5d864
perf(fuse): O(length) range reads via cache.read_range; typed CacheError
Amantux Oct 9, 2026
1da44eb
fix(jobs): restore journals physical_state_unknown via the shared helper
Amantux Oct 9, 2026
feae684
merge: fleet/review-fixes (second adversarial review)
Amantux Oct 9, 2026
30c1354
docs(fuse): gateway handle-token semantics
Amantux Oct 9, 2026
c937589
fix(protocols): rig survives malformed stubs and resets offline stubs…
Amantux Oct 9, 2026
159419a
feat(reconcile): cross-job journal query and pending-reconciliation set
Amantux Oct 10, 2026
fcdd6ef
fuse cache: per-entry integrity sidecar + open-time verify_entry
Amantux Oct 10, 2026
b19fd7c
feat(reconcile): refuse unreconciled drives in scheduler and load hel…
Amantux Oct 10, 2026
9bab58f
test(protocols): real SMB byte-range lock conflict across two sessions
Amantux Oct 10, 2026
3919499
test(mutation): add validator/import-guard/safety/policy tests to mut…
Amantux Oct 10, 2026
bd27981
feat(reconcile): reconcile_drive action, recovery report field, API r…
Amantux Oct 10, 2026
f11f168
test: add StatefulMtxRunner fake for the mtx changer CLI
Amantux Oct 10, 2026
5047a03
fuse cache: persist LRU index across restarts
Amantux Oct 10, 2026
1c965f1
feat(emulator): env-driven AML fault profile parser and counters
Amantux Oct 10, 2026
de61888
feat(catalog): persist NAS pool replication/protection and add NAS do…
Amantux Oct 10, 2026
144746e
JobQueue: persist jobs in the catalog jobs table
Amantux Oct 10, 2026
21a5aab
test(contract): add scsi+fake-ltfs pairing over RealLibraryBackend
Amantux Oct 10, 2026
7001c40
fuse cache: loop os.pread in read_range until length or EOF
Amantux Oct 10, 2026
f834429
feat(catalog): CRUD for persisted NAS reservations, export sets, vaul…
Amantux Oct 10, 2026
9ed7491
docs(test-plan): add scsi+fake-ltfs to the contract pairing table
Amantux Oct 10, 2026
a931148
fix(mutation): run mutmut's pytest sessions without capture
Amantux Oct 10, 2026
f7b26a3
test(mutation): baseline policies.py at 23 survivors (37 mutants, 52 s)
Amantux Oct 10, 2026
2371edb
test: fuse cache integrity, restart index, chunked pread
Amantux Oct 10, 2026
64e1b36
test(protocols): un-skip NFS ACL scenario; pin Ganesha 4.3 ACL limit
Amantux Oct 10, 2026
481d35a
feat(nas): catalog-backed ReservationLedger and span-aware restore pl…
Amantux Oct 10, 2026
3789b9a
test(reconcile): pending set, scheduler skip/refuse, load refusal, AP…
Amantux Oct 10, 2026
e6621bc
feat(api): expose pool replication/protection and NAS reservation, ex…
Amantux Oct 10, 2026
ba1a22f
test(mutation): baseline recovery.py at 43 survivors (134 mutants, 12…
Amantux Oct 10, 2026
0aac146
JobQueue: drive and changer claims are catalog leases
Amantux Oct 10, 2026
54b414a
Test JobQueue jobs and claims across two catalog sessions
Amantux Oct 10, 2026
6d50b45
Docs: record the JobQueue persistent-lease follow-up
Amantux Oct 10, 2026
e691a17
test(mutation): baseline safety/import_guard.py at 20 survivors (86 m…
Amantux Oct 10, 2026
b6ba865
test(mutation): baseline nas/manifest_validator.py at 74 survivors (2…
Amantux Oct 10, 2026
f36db67
test(mutation): kill 32 survivors in policies/recovery, ratchet 23->2…
Amantux Oct 10, 2026
392ff62
docs(mutation): 6/6 modules baselined (header + roadmap item 16)
Amantux Oct 10, 2026
f3087dd
Merge branch 'fleet2/reconcile' into feat/persistent-drive-leases
Amantux Oct 10, 2026
d2f76b2
Merge branch 'fleet2/nas-persist' into feat/persistent-drive-leases
Amantux Oct 10, 2026
f990785
Merge branch 'fleet2/cache-integrity' into feat/persistent-drive-leases
Amantux Oct 10, 2026
f569d5b
Merge branch 'fleet2/scsi-pairing' into feat/persistent-drive-leases
Amantux Oct 10, 2026
15a8d16
Merge branch 'fleet2/protocol-gaps' into feat/persistent-drive-leases
Amantux Oct 10, 2026
4cf1e57
Merge branch 'fleet2/queue' into feat/persistent-drive-leases
Amantux Oct 10, 2026
2d6df7a
Merge branch 'fleet2/mutation-baseline' into fleet2/followup
Amantux Oct 10, 2026
7d0f5e6
Merge branch 'fleet2/mutation-baseline' into feat/persistent-drive-le…
Amantux Oct 10, 2026
f213c86
feat(emulator): AML fault hooks (reboot 503, load 409, checksum retry…
Amantux Oct 10, 2026
24b37f8
Add targeted and exclude-aware drive lease acquisition
Amantux Oct 10, 2026
04c845e
test(i3): import fault presets from emulator; skip client faults when…
Amantux Oct 10, 2026
bf8a4e5
docs(emulator): document OPENBLADE_EMULATOR_FAULT_PROFILE in contract…
Amantux Oct 10, 2026
9a38eec
Merge branch 'fleet2/emulator-faults' into feat/persistent-drive-leases
Amantux Oct 10, 2026
e8795ee
feat(emulator): wire AML fault profile into the latency middleware
Amantux Oct 10, 2026
59be7da
Claim queue drive/changer slots with targeted leases
Amantux Oct 10, 2026
7bce7bb
Test that gateway on_open evicts a corrupt cache entry and re-hydrates
Amantux Oct 10, 2026
7a614e3
Merge branch 'fleet2/followup' into feat/persistent-drive-leases
Amantux Oct 10, 2026
02c52b4
chore(integration): round-2 merge fixes
Amantux Oct 10, 2026
5d2cf35
fix(fuse-cache): accept any checksum string for sample offset; reject…
Amantux Oct 10, 2026
7689ab8
fix(job-queue): reconciliation barrier on claim_drive; heartbeat clai…
Amantux Oct 10, 2026
7a0c7d7
fix(jobs): fail closed when physical_state_unknown cannot be journale…
Amantux Oct 10, 2026
69f888b
fix(reconcile): order journal by id; exclude pending barcodes (S1, S2)
Amantux Oct 10, 2026
29857ba
fix(nas-capacity): atomic reservation check-and-insert under BEGIN IM…
Amantux Oct 10, 2026
c042391
fix(scheduler): refuse barcodes pending reconciliation
Amantux Oct 10, 2026
6feebc6
Merge branch 'fleet2/fix-misc' into feat/persistent-drive-leases
Amantux Oct 10, 2026
d722f59
fix(jobs): keep cleanup and the original lane error when lease releas…
Amantux Oct 10, 2026
d3c1d75
fix(recovery): skip queue-claim leases in mismatch check; JournalWrit…
Amantux Oct 10, 2026
e5ee704
style: ruff format test_sharded_archive_atomicity.py (format-only)
Amantux Oct 10, 2026
c13cf24
docs(decisions): reconciliation fail-closed rule, barcode exclusion, …
Amantux Oct 10, 2026
8dadd60
Merge branch 'fleet2/fix-journal' into feat/persistent-drive-leases
Amantux Oct 10, 2026
6db8d73
docs: roadmap status 2026-10-10 and tech-debt after round-2 fleet
Amantux Oct 10, 2026
7435dd1
fix(fuse-cache): only a whole-component ".." is an unsafe cache key
Amantux Oct 10, 2026
dfbd8f9
feat(nas): planner refuses plans exceeding pool reservation budget
Amantux Oct 11, 2026
47470e5
feat(compat): add compat_capture replay/capture/diff tool with sanitizer
Amantux Oct 11, 2026
111b7e3
test(compat): sanitizer rules, provenance refusal and determinism for…
Amantux Oct 11, 2026
59066d2
feat(aml): mark MFA-required logins as pending sessions (inferred)
Amantux Oct 11, 2026
eeb5291
build(nas-protocols): serve NFS from Fedora 41 Ganesha 5.9 with VFS A…
Amantux Oct 11, 2026
81effc5
feat(nas): archive plans book a pool reservation against the budget
Amantux Oct 11, 2026
7c0d395
ci(mhvtl-weekly): run drive-identity bridge test in the no-LTFS suite…
Amantux Oct 11, 2026
6f88b18
docs(roadmap): item 23 bridge is implemented, not yet certified on metal
Amantux Oct 11, 2026
ca6e47a
test(protocols): assert a real NFSv4 DENY ACE is enforced over NFS
Amantux Oct 11, 2026
a41eb43
docs: NFSv4 ACL enforcement is now a real protocol-rig scenario
Amantux Oct 11, 2026
17b4e51
feat(nas): scratch-stock health component and threshold API
Amantux Oct 11, 2026
0751fcf
Merge fleet3/nfs-acl: real NFSv4 ACL scenario on the protocol rig
Amantux Oct 11, 2026
0b73709
Merge fleet3/phase7: bridge test in mhvtl lane, roadmap item 23 corre…
Amantux Oct 11, 2026
e9b2ff5
fix(compat): scrub XML-body tokens and cookie expiry; keep bad-passwo…
Amantux Oct 11, 2026
f848464
test(compat): add 12 self-captured aml cases and self-captured source…
Amantux Oct 11, 2026
9497817
docs(compat): appliance capture procedure, redaction list and self-ca…
Amantux Oct 11, 2026
db8766b
Merge fleet3/capture: compatibility capture/sanitize tool, self-captu…
Amantux Oct 11, 2026
28a90ff
feat(upload): share-push plans book a pool reservation like /nas/arch…
Amantux Oct 11, 2026
62ece7b
feat(aml): gate MFA-pending sessions to the MFA challenge routes and …
Amantux Oct 11, 2026
3764b78
test(i3): emulator-only MFA-pending session round trip
Amantux Oct 11, 2026
4419c60
docs(aml): describe the inferred MFA-pending login state
Amantux Oct 11, 2026
754fdc6
feat(nas): release a plan's pool reservation when its ingest job ends
Amantux Oct 11, 2026
8ef15e9
Merge fleet3/mfa: inferred MFA-pending session state in the AML emulator
Amantux Oct 11, 2026
56635cb
docs: capacity reservations decision record, tech-debt, wiki api regen
Amantux Oct 11, 2026
d6ee365
test(compat): MFA setup hook + inferred MFA-pending login case
Amantux Oct 11, 2026
18b9faf
docs(roadmap): refresh status rows 3, 18, 19, 22, 23 (as of 2026-10-11)
Amantux Oct 11, 2026
544dd44
Merge fleet3/followup: compat MFA setup hook + case, roadmap status rows
Amantux Oct 11, 2026
f06a92a
Merge fleet3/capacity: pool reservation budget, booking + release, sc…
Amantux Oct 11, 2026
eb39446
fix(compat): sanitizer masks nested secret leaves, XML attrs, tagged …
Amantux Oct 11, 2026
e4d8d06
fix(nas): derive pool budget server-side; refuse client capacity inpu…
Amantux Oct 11, 2026
6f3a44e
fix(aml): MFA-pending login never changes status or body, strict mode…
Amantux Oct 11, 2026
2f77cc2
build(nas): pin nfs-ganesha 5.9 in the Fedora stage
Amantux Oct 11, 2026
36e7607
Merge fleet3/fix-misc: sanitizer nested/XML-attr/Basic leaks, MFA hea…
Amantux Oct 11, 2026
201ee40
fix(nas): book pool capacity at ingest start, not at plan preview (S2)
Amantux Oct 11, 2026
47e8e69
fix(nas): count scratch from library inventory; exclude VG members fr…
Amantux Oct 11, 2026
3b4722a
fix(nas): never let a failed reservation release mask the ingest erro…
Amantux Oct 11, 2026
ccf7107
fix(nas): release the plan booking when the ingest executor raises (S…
Amantux Oct 11, 2026
63761c8
docs(nas): record server-derived budget, booking at start, inventory …
Amantux Oct 11, 2026
7d82885
test(nas): stop sending available_tapes with pool in the e2e archive …
Amantux Oct 11, 2026
144b7d0
Merge fleet3/fix-capacity: server-derived pool budget (B1), booking a…
Amantux Oct 11, 2026
3841c59
fix(demo): let the server derive the pool tape set in the MVP plan re…
Amantux Oct 11, 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
4 changes: 4 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
self-hosted-runner:
labels:
- i3
- openblade-production
112 changes: 112 additions & 0 deletions .github/workflows/_emulator-boot-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Reusable: boot the mock-backend emulator API on 127.0.0.1:8000, wait for
# /health, then run pytest against it. Callers: emulator-change-gates.yml,
# i3-emulator-compliance.yml. Check names become "<caller job> / boot-test".
name: _emulator-boot-test

on:
workflow_call:
inputs:
timing_profile:
description: I3_TIMING_PROFILE for both the server and pytest.
type: string
default: instant
pytest_args:
description: >-
Space-separated pytest arguments (paths, -m, -q ...). Word-split by
the shell on purpose; must not contain quotes.
type: string
required: true
followup_pytest_args:
description: Optional second pytest run against the same booted API.
type: string
default: ""
python_version:
type: string
default: "3.12"
emulator_profile:
description: EMULATOR_PROFILE for the booted server and pytest ("" = default shape).
type: string
default: ""
validate_contract:
description: Run tools/emulator_spec/validate_cross_repo_contract.py first.
type: boolean
default: true
db_name:
description: Basename of the throwaway sqlite DB under /tmp.
type: string
default: openblade-emulator
artifact_name:
description: Upload test-results/ + the API log under this name ("" = no upload).
type: string
default: ""

permissions:
contents: read

jobs:
boot-test:
name: boot-test
runs-on: ubuntu-latest
env:
I3_TEST_MODE: emulator
I3_TIMING_PROFILE: ${{ inputs.timing_profile }}
I3_AML_URL: http://127.0.0.1:8000
PYTEST_ARGS: ${{ inputs.pytest_args }}
FOLLOWUP_PYTEST_ARGS: ${{ inputs.followup_pytest_args }}
DB_PATH: /tmp/${{ inputs.db_name }}.db
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
# Job-wide EMULATOR_PROFILE only when one was given: an empty value must
# mean "unset" (default shape) for every later step, not "profile named ''".
- name: Export EMULATOR_PROFILE
env:
PROFILE: ${{ inputs.emulator_profile }}
run: |
if [ -n "$PROFILE" ]; then echo "EMULATOR_PROFILE=$PROFILE" >> "$GITHUB_ENV"; fi
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ inputs.python_version }}
cache: "pip"
- run: pip install -e '.[dev]'
- if: ${{ inputs.validate_contract }}
run: python3 tools/emulator_spec/validate_cross_repo_contract.py
- run: python3 tools/emulator_spec/generate_matrix_endpoint_catalog.py
- name: Boot emulator API
run: |
rm -f "$DB_PATH"
OPENBLADE_BACKEND=mock OPENBLADE_DB_URL="sqlite:///$DB_PATH" \
nohup uvicorn openblade.api.main:app --host 127.0.0.1 --port 8000 >/tmp/openblade-api.log 2>&1 &
- name: Wait for API health
run: |
python - <<'PY'
import time
import urllib.request
for _ in range(60):
try:
with urllib.request.urlopen("http://127.0.0.1:8000/health", timeout=2) as response:
if response.status == 200:
raise SystemExit(0)
except Exception:
time.sleep(1)
raise SystemExit("API did not become healthy in time")
PY
- run: mkdir -p test-results
- name: Run pytest against the booted emulator
run: |
# shellcheck disable=SC2086 # PYTEST_ARGS is a word list by contract
python -m pytest $PYTEST_ARGS
- name: Follow-up pytest run
if: ${{ inputs.followup_pytest_args != '' }}
run: |
# shellcheck disable=SC2086 # word list by contract
python -m pytest $FOLLOWUP_PYTEST_ARGS
- name: Upload artifacts
if: ${{ always() && inputs.artifact_name != '' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ inputs.artifact_name }}
path: |
test-results/
/tmp/openblade-api.log
13 changes: 9 additions & 4 deletions .github/workflows/auto-merge-trusted.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
name: Auto-merge trusted PRs

on:
# dangerous-triggers is ignored on `on:` below: this workflow runs only the GitHub API via
# github-script on the trusted-author allowlist; never checks out or executes
# PR code, which is what makes workflow_run dangerous.
on: # zizmor: ignore[dangerous-triggers] -- see comment above
workflow_run:
workflows: ["CI"]
types: [completed]

permissions:
contents: write
pull-requests: write
contents: read

jobs:
merge-trusted-pr:
if: >
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Merge trusted PRs targeting master
uses: actions/github-script@v7
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
with:
script: |
const owner = context.repo.owner;
Expand Down
95 changes: 68 additions & 27 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ jobs:
cicd: ${{ steps.filter.outputs.cicd }}
wiki: ${{ steps.filter.outputs.wiki }}
steps:
- uses: actions/checkout@v5
- uses: dorny/paths-filter@v3
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: dorny/paths-filter@0e4a8c6effa4802afeda77dc8d303f8176d7dfad # v3.0.4
id: filter
with:
filters: |
Expand Down Expand Up @@ -99,8 +101,10 @@ jobs:
# goes red, the fix is `ruff check --fix` / `ruff format` with the PINNED
# version, never a version bump in the same change.
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
Expand All @@ -122,8 +126,10 @@ jobs:
# `# type: ignore` comments left in openblade/ (down from 18) carries its
# justification at the site.
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
Expand All @@ -136,8 +142,10 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.api == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
Expand All @@ -162,8 +170,10 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.api == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
Expand All @@ -185,8 +195,10 @@ jobs:
env:
I3_TIMING_PROFILE: instant
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
Expand Down Expand Up @@ -216,8 +228,10 @@ jobs:
run:
working-directory: frontend
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "20"
cache: "npm"
Expand All @@ -234,17 +248,16 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.webflask == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
- run: pip install -e '.[dev]'
# BLOCKING mypy, scoped to this package alone. `mypy openblade` in
# backend-typecheck has to stay advisory because of ~300 pre-existing errors
# in the god-file modules; openblade/web_flask is clean under strict mode
# today, and this job is what keeps it that way instead of letting it join
# the backlog.
# BLOCKING mypy, scoped to this package alone, so a web_flask-only change
# is gated here too (backend-typecheck is path-filtered to backend paths).
- run: mypy openblade/web_flask
# Redundant with backend-tests (tests/unit covers this file) but kept so the
# job is a complete gate on its own for a web_flask-only change. Seconds.
Expand All @@ -260,8 +273,10 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.wiki == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
Expand All @@ -278,8 +293,10 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.cicd == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- run: python -m pip install --upgrade pip pyyaml yamllint
Expand All @@ -297,6 +314,26 @@ jobs:
- name: yamllint workflows (real YAML errors — see .yamllint)
run: yamllint -c .yamllint .github/workflows/

# Changed-path ownership: every changed openblade/** or tests/** path must map
# to a test category in tools/ci_ownership.toml, so a new module can't land
# outside every CI lane unnoticed. Always runs (not path-filtered).
ownership:
name: ownership
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Check changed paths have an owning test category
env:
# PRs diff against their target branch; pushes/dispatch against master.
BASE_REF: ${{ github.base_ref || 'master' }}
run: python tools/ci_ownership.py --base "origin/$BASE_REF"

# Single always-running aggregation gate. Make THIS the only required
# branch-protection check (plus operability-gate). It understands a valid
# `skipped` result from path-filtered jobs and fails on any real failure or
Expand All @@ -305,6 +342,7 @@ jobs:
ci-gate:
name: ci-gate
needs:
- ownership
- backend-lint
- backend-typecheck
- backend-tests
Expand All @@ -326,6 +364,7 @@ jobs:
*) echo "FAIL $1=$2"; fail=1 ;;
esac
}
check ownership "${{ needs.ownership.result }}"
check backend-tests "${{ needs.backend-tests.result }}"
check api-aml-integration "${{ needs.api-aml-integration.result }}"
check i3-smoke "${{ needs.i3-smoke.result }}"
Expand Down Expand Up @@ -360,8 +399,10 @@ jobs:
env:
I3_TIMING_PROFILE: instant
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: "pip"
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
paths:
- .github/workflows/copilot-setup-steps.yml

permissions:
contents: read

jobs:
copilot-setup-steps:
runs-on: ubuntu-latest
Expand All @@ -18,4 +21,6 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5
# zizmor: ignore[artipacked] -- the Copilot coding agent works in this
# checkout and may need its git credentials; nothing here uploads artifacts.
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
Loading
Loading