Skip to content

Commit 4397c3f

Browse files
Jonathan D.A. Jewellclaude
andcommitted
feat: production hardening — document storage, CI, docs, formatting
Implement content-addressed document storage in IPP server (SHA-256 dedup), add GitHub Actions CI workflow, update all human and machine documentation (replace template placeholders, rewrite SCM files with real project data), apply cargo fmt across workspace. Key changes: - IPP server persists received documents to disk by content hash - 7 new document storage tests (68 total, all passing) - CI workflow: check, test, clippy, fmt (SHA-pinned actions) - README.adoc rewritten with stats, dep graph, verification section - All SCM files updated with real component statuses and metrics - SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md de-templated - ABI-FFI-README.md updated with presswerk-specific examples - cargo fmt applied across all crates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5d3b421 commit 4397c3f

38 files changed

Lines changed: 1016 additions & 622 deletions

File tree

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Presswerk — Rust CI (build, test, lint, format)
3+
4+
name: CI
5+
6+
on:
7+
push:
8+
branches: [main]
9+
pull_request:
10+
branches: [main]
11+
12+
permissions: read-all
13+
14+
jobs:
15+
test:
16+
name: Test
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
20+
- uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
21+
with:
22+
components: clippy, rustfmt
23+
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
24+
25+
- name: Install system dependencies
26+
run: |
27+
sudo apt-get update
28+
sudo apt-get install -y libxdo-dev libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
29+
30+
- name: Check
31+
run: cargo check --workspace
32+
33+
- name: Test (library crates)
34+
run: cargo test -p presswerk-core -p presswerk-security -p presswerk-document -p presswerk-print
35+
36+
- name: Clippy
37+
run: cargo clippy --workspace -- -D warnings
38+
39+
- name: Format check
40+
run: cargo fmt --all -- --check

.machine_readable/AGENTIC.scm

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,28 @@
11
;; SPDX-License-Identifier: PMPL-1.0-or-later
2-
;; Reserved for future use.
2+
(agentic (metadata (version "0.1.0") (last-updated "2026-02-14"))
3+
(agent-capabilities
4+
(capability "code-generation"
5+
(scope "crates/")
6+
(constraints ("must pass cargo clippy -- -D warnings"
7+
"must pass cargo test --workspace"
8+
"unsafe blocks require // SAFETY: comment"
9+
"no banned patterns: believe_me, Admitted, transmute")))
10+
(capability "documentation"
11+
(scope ("README.adoc" ".machine_readable/" "ABI-FFI-README.md"))
12+
(constraints ("maintain SPDX headers"
13+
"SCM files only in .machine_readable/")))
14+
(capability "formal-verification"
15+
(scope "src/abi/")
16+
(constraints ("no Admitted proofs"
17+
"no believe_me"
18+
"all proofs must be total")))
19+
(capability "security-scanning"
20+
(tool "panic-attack assail .")
21+
(expected-baseline "0 critical, 4 high (FFI unavoidable), 5 medium")))
22+
(session-protocol
23+
(on-enter ("read 0-AI-MANIFEST.a2ml"
24+
"read .machine_readable/STATE.scm"
25+
"run cargo test --workspace"))
26+
(on-exit ("update .machine_readable/STATE.scm"
27+
"run cargo clippy --workspace -- -D warnings"
28+
"commit if changes made"))))

.machine_readable/ECOSYSTEM.scm

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
;; SPDX-License-Identifier: PMPL-1.0-or-later
2-
(ecosystem (metadata (version "0.1.0") (last-updated "2026-02-13"))
2+
(ecosystem (metadata (version "0.2.0") (last-updated "2026-02-14"))
33
(project (name "presswerk") (purpose "High-assurance local print router/server for mobile") (role "end-user-app"))
4+
(forges
5+
(forge "github" (url "https://github.com/hyperpolymath/presswerk"))
6+
(forge "gitlab" (url "https://gitlab.com/hyperpolymath/presswerk")))
47
(related-projects
5-
(project "dotmatrix-fileprinter" (relationship "sibling") (description "Desktop printer app (ReScript + Tauri)"))
6-
(project "proven" (relationship "dependency") (description "Idris2 formally verified library — ABI proofs"))
7-
(project "hypatia" (relationship "consumer") (description "Neurosymbolic CI/CD — scans presswerk"))
8-
(project "gitbot-fleet" (relationship "consumer") (description "Bot orchestration for automated fixes"))
9-
(project "panic-attacker" (relationship "tool") (description "Security scanning tool"))))
8+
(project "dotmatrix-fileprinter" (relationship "sibling") (description "Desktop printer app (ReScript + Tauri) — different scope, same domain"))
9+
(project "proven" (relationship "dependency") (description "Idris2 formally verified library — ABI proofs foundation"))
10+
(project "hypatia" (relationship "consumer") (description "Neurosymbolic CI/CD — scans presswerk for security"))
11+
(project "gitbot-fleet" (relationship "consumer") (description "Bot orchestration — 7 bots with presswerk-specific directives"))
12+
(project "panic-attacker" (relationship "tool") (description "Security scanning tool — 10 weak points found, 0 critical"))
13+
(project "verisimdb-data" (relationship "consumer") (description "Security findings database — ingests panic-attack scan results"))
14+
(project "echidna" (relationship "tool") (description "Formal proofing tool — validates Idris2 ABI proofs"))
15+
(project "rsr-template-repo" (relationship "template") (description "RSR template — scaffolded presswerk structure"))))

.machine_readable/META.scm

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
;; SPDX-License-Identifier: PMPL-1.0-or-later
2-
(meta (metadata (version "0.1.0") (last-updated "2026-02-13"))
3-
(project-info (type "mobile-app") (languages (rust idris2 zig)) (license "PMPL-1.0-or-later"))
2+
(meta (metadata (version "0.2.0") (last-updated "2026-02-14"))
3+
(project-info
4+
(type "mobile-app")
5+
(languages (rust idris2 zig))
6+
(license "PMPL-1.0-or-later")
7+
(author "Jonathan D.A. Jewell (hyperpolymath) <jonathan.jewell@open.ac.uk>")
8+
(framework "dioxus-0.7")
9+
(platforms (ios android desktop)))
410
(architecture-decisions
511
(adr "ADR-001" (title "Dioxus for mobile UI") (status "accepted")
612
(decision "Use Dioxus 0.7+ — pure Rust, React-like, mobile-native"))
713
(adr "ADR-002" (title "age for encryption at rest") (status "accepted")
814
(decision "Use age crate with X25519 passphrase-based key derivation"))
915
(adr "ADR-003" (title "IPP server on port 631") (status "accepted")
10-
(decision "Phone as network printer via IPP + mDNS advertisement"))
16+
(decision "Phone as network printer via raw TCP IPP + mDNS advertisement"))
1117
(adr "ADR-004" (title "Pure-Rust OCR via ocrs") (status "accepted")
12-
(decision "No C deps — ocrs ONNX-based pure Rust"))
18+
(decision "No C deps — ocrs ONNX-based pure Rust neural text recognition"))
1319
(adr "ADR-005" (title "SQLite for persistence") (status "accepted")
14-
(decision "rusqlite bundled for job queue + audit trail"))))
20+
(decision "rusqlite bundled for job queue + audit trail — survives app restart"))
21+
(adr "ADR-006" (title "Bridge.idr for platform FFI safety") (status "accepted")
22+
(decision "Extend Idris2 ABI with Bridge.idr proving toll-free bridging, keychain semantics, thread requirements, JNI invariants, and opaque handle safety"))
23+
(adr "ADR-007" (title "Content-addressed document storage") (status "accepted")
24+
(decision "Store received documents by SHA-256 hash — deduplication, integrity verification, simple retrieval")))
25+
(development-practices
26+
(unsafe-policy "Every unsafe block requires // SAFETY: comment referencing ABI proof")
27+
(banned-patterns ("believe_me" "Admitted" "unsafePerformIO" "transmute"))
28+
(testing "cargo test --workspace — 61 unit tests, clippy zero warnings")
29+
(security-scanning "panic-attack assail . — 10 weak points, 0 critical")))

.machine_readable/NEUROSYM.scm

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,42 @@
11
;; SPDX-License-Identifier: PMPL-1.0-or-later
2-
;; Reserved for future use.
2+
(neurosym (metadata (version "0.1.0") (last-updated "2026-02-14"))
3+
(integration
4+
(hypatia-scan
5+
(enabled #t)
6+
(workflow ".github/workflows/hypatia-scan.yml")
7+
(triggers ("push to main" "pull request")))
8+
(panic-attack
9+
(enabled #t)
10+
(command "panic-attack assail .")
11+
(baseline-findings 10)
12+
(critical-threshold 0)
13+
(high-threshold 4)))
14+
(formal-verification
15+
(idris2-abi
16+
(files ("src/abi/Types.idr"
17+
"src/abi/Protocol.idr"
18+
"src/abi/Encryption.idr"
19+
"src/abi/Layout.idr"
20+
"src/abi/Bridge.idr"))
21+
(properties ("job-status-injectivity"
22+
"ipp-op-code-injectivity"
23+
"valid-state-transitions"
24+
"terminal-state-no-exit"
25+
"encrypt-decrypt-roundtrip"
26+
"ciphertext-size-bounds"
27+
"struct-alignment"
28+
"toll-free-bridging-symmetry"
29+
"toll-free-bridging-transitivity"
30+
"keychain-store-load"
31+
"keychain-delete-load"
32+
"keychain-last-write-wins"
33+
"thread-requirement-safety"
34+
"jni-invariants"
35+
"opaque-handle-safety"))
36+
(banned ("Admitted" "believe_me" "assert_total" "unsafePerformIO"))))
37+
(zig-ffi
38+
(files ("ffi/zig/src/main.zig"))
39+
(tests 5)
40+
(exports ("presswerk_init" "presswerk_free" "presswerk_validate_transition"
41+
"presswerk_hash" "presswerk_last_error" "presswerk_version"
42+
"presswerk_build_info" "presswerk_is_initialized"))))

.machine_readable/PLAYBOOK.scm

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,40 @@
11
;; SPDX-License-Identifier: PMPL-1.0-or-later
2-
;; Reserved for future use.
2+
(playbook (metadata (version "0.1.0") (last-updated "2026-02-14"))
3+
(recipes
4+
(recipe "dev"
5+
(description "Run desktop development server")
6+
(command "just dev")
7+
(prerequisites ("cargo installed" "dioxus-cli installed")))
8+
(recipe "test"
9+
(description "Run all unit tests")
10+
(command "just test")
11+
(expected "61 tests pass, 0 failures"))
12+
(recipe "lint"
13+
(description "Clippy lint with deny warnings")
14+
(command "just lint")
15+
(expected "0 warnings"))
16+
(recipe "assail"
17+
(description "Security scan with panic-attack")
18+
(command "just assail")
19+
(expected "0 critical findings"))
20+
(recipe "verify-abi"
21+
(description "Type-check all Idris2 ABI proofs")
22+
(command "just verify-abi")
23+
(prerequisites ("idris2 installed")))
24+
(recipe "ios-build"
25+
(description "Build for iOS simulator")
26+
(command "just ios")
27+
(prerequisites ("macOS" "Xcode 15+" "dioxus-cli")))
28+
(recipe "android-build"
29+
(description "Build for Android emulator")
30+
(command "just android")
31+
(prerequisites ("Android NDK r26+" "dioxus-cli"))))
32+
(release-checklist
33+
("cargo test --workspace passes"
34+
"cargo clippy --workspace -- -D warnings clean"
35+
"panic-attack assail . — 0 critical"
36+
"just verify-abi — all Idris2 proofs type-check"
37+
".machine_readable/STATE.scm updated"
38+
"README.adoc version bumped"
39+
"git tag -s vX.Y.Z"
40+
"push to github, gitlab")))

.machine_readable/STATE.scm

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,40 @@
11
;; SPDX-License-Identifier: PMPL-1.0-or-later
2-
(state (metadata (version "0.1.0") (last-updated "2026-02-13") (status active))
2+
(state (metadata (version "0.2.0") (last-updated "2026-02-14") (status active))
33
(project-context
44
(name "presswerk")
55
(purpose "High-assurance local print router and server for iOS/Android")
6-
(completion-percentage 15))
6+
(completion-percentage 65))
77
(components
8-
(component "presswerk-core" (status "complete") (description "Shared types, errors, config"))
9-
(component "presswerk-security" (status "implemented") (description "Encrypted storage, audit trail, TLS"))
10-
(component "presswerk-document" (status "implemented") (description "PDF ops, image processing, scanning"))
11-
(component "presswerk-print" (status "implemented") (description "IPP client/server, mDNS discovery, job queue"))
12-
(component "presswerk-bridge" (status "scaffolded") (description "iOS/Android native bridges — stubs"))
13-
(component "presswerk-app" (status "scaffolded") (description "Dioxus UI with all pages")))
8+
(component "presswerk-core" (status "complete") (description "Shared types, errors, config — 244-line types, 70-line errors"))
9+
(component "presswerk-security" (status "complete") (description "age encryption, SHA-256 integrity, Ed25519 certs, SQLite audit trail — 14 tests"))
10+
(component "presswerk-document" (status "complete") (description "PDF read/merge/split/rotate, image processing, scan enhancement, OCR — 7 tests"))
11+
(component "presswerk-print" (status "complete") (description "Full IPP/1.1 server (1936 lines), IPP client, mDNS discovery, SQLite job queue — 40 tests"))
12+
(component "presswerk-bridge" (status "unverified") (description "iOS objc2 (894 lines) + Android JNI (973 lines) — detailed but untested on device"))
13+
(component "presswerk-app" (status "functional") (description "Dioxus UI with 10 pages, routing, AppServices layer, settings"))
14+
(component "abi-proofs" (status "complete") (description "5 Idris2 files: Types, Protocol, Encryption, Layout, Bridge — no Admitted"))
15+
(component "ffi-zig" (status "complete") (description "C-compatible FFI with 5 tests — lifecycle, transitions, hash, version")))
16+
(metrics
17+
(rust-files 43)
18+
(rust-lines 10219)
19+
(idris2-files 5)
20+
(zig-files 3)
21+
(unit-tests 61)
22+
(clippy-warnings 0)
23+
(panic-attack-critical 0)
24+
(panic-attack-high 4)
25+
(panic-attack-medium 5))
1426
(current-position
15-
(phase "Phase 1Scaffolding + Core")
16-
(milestone "All crates created with real implementations, UI pages scaffolded")
27+
(phase "Phase 7Production Hardening")
28+
(milestone "Core implementation complete, formal verification done, doc storage implemented")
1729
(next-actions
18-
("Wire discovery into Home page"
19-
"Wire IPP client into Print page"
20-
"Implement iOS bridge methods"
21-
"Test on iOS simulator")))
30+
("Test iOS bridge on device/simulator (requires macOS + Xcode)"
31+
"Test Android bridge on device/emulator (requires NDK)"
32+
"Add TLS to IPP server (rustls cert already generated)"
33+
"Add rate limiting to IPP server"
34+
"Apple Developer Team ID for iOS signing")))
2235
(blockers-and-issues
23-
(blocker "iOS/Android bridges are stubs — need Xcode/NDK to test")
24-
(blocker "ippper crate availability not confirmed for print server")
25-
(note "Desktop dev mode works without mobile bridges via stub bridge")))
36+
(blocker "iOS bridge never compiled on target — need macOS + Xcode")
37+
(blocker "Android bridge never compiled on target — need NDK")
38+
(blocker "Dioxus.toml team_id empty — need Apple Developer account")
39+
(note "Desktop dev mode works via stub bridge")
40+
(note "All 4 panic-attack High findings are unavoidable FFI unsafe — covered by Bridge.idr proofs")))

0-AI-MANIFEST.a2ml

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,62 @@ These 6 SCM files MUST exist in `.machine_readable/` directory ONLY:
2525

2626
### Bot Directives: `.bot_directives/` ONLY
2727

28-
Bot-specific instructions for the gitbot-fleet.
28+
Bot-specific instructions for the gitbot-fleet (7 bots: rhodibot, echidnabot, sustainabot, glambot, seambot, finishbot, robot-repo-automaton).
2929

3030
### Source Code: `crates/` ONLY
3131

3232
All Rust source code lives in the `crates/` workspace directory. The six crates are:
3333
- `presswerk-core` — Shared types, errors, config (no internal deps)
34-
- `presswerk-security` — Encrypted storage, audit trail, TLS (depends: core)
35-
- `presswerk-document` — PDF, image, scanning (depends: core)
36-
- `presswerk-print` — IPP client/server, mDNS, job queue (depends: core, security)
37-
- `presswerk-bridge` — iOS (objc2) + Android (JNI) bridges (depends: core)
38-
- `presswerk-app` — Dioxus UI (depends: all above)
34+
- `presswerk-security` — Encrypted storage, audit trail, TLS certs (depends: core)
35+
- `presswerk-document` — PDF ops, image processing, scanning, OCR (depends: core)
36+
- `presswerk-print` — IPP client/server, mDNS discovery, job queue (depends: core, security)
37+
- `presswerk-bridge` — iOS (objc2) + Android (JNI) native bridges (depends: core)
38+
- `presswerk-app` — Dioxus UI with 10 pages (depends: all above)
3939

4040
### Formal Verification: `src/abi/` and `ffi/zig/`
4141

42-
Idris2 ABI proofs in `src/abi/`, Zig FFI in `ffi/zig/`, generated C headers in `generated/abi/`.
42+
Idris2 ABI proofs in `src/abi/` (5 files):
43+
- **Types.idr** — Core types with C ABI sizes, platform detection, injectivity proofs
44+
- **Protocol.idr** — IPP op-code injectivity, job state machine (valid transitions, terminal states)
45+
- **Encryption.idr** — encrypt/decrypt roundtrip, ciphertext bounds, key separation
46+
- **Layout.idr** — Struct memory layout and alignment proofs
47+
- **Bridge.idr** — Toll-free bridging, keychain semantics, thread safety, JNI invariants
48+
49+
Zig FFI in `ffi/zig/` — C-compatible exports (8 functions, 5 tests).
50+
Generated C headers in `generated/abi/`.
4351

4452
## CORE INVARIANTS
4553

4654
1. **No SCM duplication** — Root must NOT contain STATE.scm, META.scm, etc.
4755
2. **Single source of truth** — `.machine_readable/` is authoritative
4856
3. **License** — All code PMPL-1.0-or-later
49-
4. **Author** — "Jonathan D.A. Jewell <jonathan.jewell@open.ac.uk>"
50-
5. **No unsafe Rust** without `// SAFETY:` comment
57+
4. **Author** — "Jonathan D.A. Jewell (hyperpolymath) <jonathan.jewell@open.ac.uk>"
58+
5. **No unsafe Rust** without `// SAFETY:` comment referencing ABI proofs
5159
6. **No banned crates** — No C-based OCR (Tesseract), no openssl (use ring/rustls)
52-
7. **Container standard** — Containerfile (not Dockerfile), Podman (not Docker), chainguard base images
60+
7. **No banned patterns** — No believe_me, Admitted, assert_total, unsafePerformIO, transmute
61+
8. **Container standard** — Containerfile (not Dockerfile), Podman (not Docker), chainguard base images
5362

5463
## SESSION STARTUP CHECKLIST
5564

5665
1. Read THIS file (0-AI-MANIFEST.a2ml) first
57-
2. Read `.machine_readable/STATE.scm` for current status
58-
3. Run `cargo test --workspace` to verify state
66+
2. Read `.machine_readable/STATE.scm` for current status (65% complete)
67+
3. Run `cargo test --workspace` to verify state (61 tests expected)
5968
4. Check for blockers in STATE.scm
6069

70+
## PROJECT STATUS
71+
72+
- **Completion:** 65%
73+
- **Stats:** 43 Rust files, 10,219 lines, 5 Idris2 ABI files, 3 Zig FFI files
74+
- **Tests:** 61 unit tests (40 print + 14 security + 7 document), 0 failures
75+
- **Clippy:** 0 warnings
76+
- **Security:** panic-attack 0 critical, 4 high (FFI — covered by Bridge.idr)
77+
- **Remotes:** GitHub + GitLab (hyperpolymath/presswerk)
78+
6179
## META
6280

63-
- **Format Version:** 1.0.0
81+
- **Format Version:** 1.1.0
6482
- **Created:** 2026-02-13
83+
- **Updated:** 2026-02-14
6584
- **Maintained By:** Jonathan D.A. Jewell (hyperpolymath)
6685
- **License:** PMPL-1.0-or-later
6786
- **Protocol:** https://github.com/hyperpolymath/0-ai-gatekeeper-protocol

0 commit comments

Comments
 (0)