diff --git a/.github/workflows/casket-pages.yml b/.github/workflows/casket-pages.yml index 0661cf7..f6d4979 100644 --- a/.github/workflows/casket-pages.yml +++ b/.github/workflows/casket-pages.yml @@ -35,7 +35,7 @@ jobs: cabal-version: '3.10' - name: Cache Cabal - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | ~/.cabal/packages diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9e32d15..c475caf 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: PMPL-1.0 +# SPDX-License-Identifier: MPL-2.0 name: CodeQL Security Analysis on: diff --git a/.github/workflows/deno-ci.yml b/.github/workflows/deno-ci.yml new file mode 100644 index 0000000..61012f0 --- /dev/null +++ b/.github/workflows/deno-ci.yml @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: MPL-2.0 +# Thin wrapper around the estate-wide reusable Deno CI bundle. +# See: hyperpolymath/standards/.github/workflows/deno-ci-reusable.yml +name: Deno CI + +on: + push: + branches: [main, master] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + deno-ci: + uses: hyperpolymath/standards/.github/workflows/deno-ci-reusable.yml@c3a62f0cfd993c23661519f571087ed16e13631c # standards#168 head diff --git a/.github/workflows/elixir-ci.yml b/.github/workflows/elixir-ci.yml index 57fa7c5..518219a 100644 --- a/.github/workflows/elixir-ci.yml +++ b/.github/workflows/elixir-ci.yml @@ -13,4 +13,4 @@ jobs: uses: hyperpolymath/standards/.github/workflows/elixir-ci-reusable.yml@4fdf4314b4ab54269adbaff10e30e483b5e86845 with: otp-version: "26" - elixir-version: "1.15" + elixir-version: "1.17" diff --git a/.github/workflows/rescript-deno-ci.yml b/.github/workflows/rescript-deno-ci.yml deleted file mode 100644 index e753eeb..0000000 --- a/.github/workflows/rescript-deno-ci.yml +++ /dev/null @@ -1,44 +0,0 @@ -# SPDX-License-Identifier: MPL-2.0 -name: ReScript/Deno CI -on: [push, pull_request] - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: denoland/setup-deno@11b63cf76cfcafb4e43f97b6cad24d8e8438f62d # v1 - with: - deno-version: v1.x - - - name: Deno lint - run: deno lint - - - name: Deno fmt check - run: deno fmt --check - - - name: Deno test - run: deno test --allow-all --coverage=coverage - - - name: ReScript build - run: | - if [ -f "rescript.json" ] || [ -f "bsconfig.json" ]; then - npm install - npx rescript - fi - - - name: Type check - run: deno check **/*.ts || true - - security: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: denoland/setup-deno@11b63cf76cfcafb4e43f97b6cad24d8e8438f62d # v1 - - name: Check permissions - run: | - # Audit for dangerous permissions - grep -rE "allow-run|allow-write|allow-env" . || echo "No dangerous permissions" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 29853b2..620ed0a 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: PMPL-1.0 +# SPDX-License-Identifier: MPL-2.0 name: OSSF Scorecard on: push: diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index 8801d53..3ba3bac 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: PMPL-1.0 +# SPDX-License-Identifier: MPL-2.0 # Prevention workflow - scans for hardcoded secrets before they reach main name: Secret Scanner diff --git a/.hypatia-ignore b/.hypatia-ignore new file mode 100644 index 0000000..a7f3469 --- /dev/null +++ b/.hypatia-ignore @@ -0,0 +1,7 @@ +# Hypatia governance bundle exemptions +# Format: : — whole-line fixed-string match +# Detail: hyperpolymath/standards/.github/workflows/governance-reusable.yml is_exempt() +# +# examples/SafeDOMExample.res — pre-existing ReScript example, scheduled +# for ReScript→AffineScript migration in affinescript#57. +cicd_rules/banned_language_file:examples/SafeDOMExample.res diff --git a/.machine_readable/6a2/STATE.a2ml b/.machine_readable/6a2/STATE.a2ml index 7c7fb3d..c32334c 100644 --- a/.machine_readable/6a2/STATE.a2ml +++ b/.machine_readable/6a2/STATE.a2ml @@ -1,14 +1,45 @@ # SPDX-License-Identifier: MPL-2.0 # STATE.a2ml — Project state checkpoint -# Converted from STATE.scm on 2026-03-15 [metadata] project = "tma-mark2" -version = "0.1.0" -last-updated = "2026-03-15" +version = "0.1.0-alpha" +last-updated = "2026-05-26" status = "active" [project-context] name = "tma-mark2" -completion-percentage = 0 -phase = "In development" +completion-percentage = 32 +phase = "alpha scaffold — v1 critical path step 1 (Repo/CubDB) landed; step 2 (FHI parser) blocked on real fixtures" +maturity = "alpha" + +[layout] +docs-index = "docs/README.adoc" +rsr-compliance = "RSR_COMPLIANCE.adoc" +ai-manifest = "0-AI-MANIFEST.a2ml" +topology = "TOPOLOGY.md" +roadmap = "ROADMAP.adoc" + +[v1-critical-path] +step-1-repo-cubdb = "done" +step-2-fhi-parser = "blocked-on-fixtures" +step-3-bouncer = "stub-only" +step-4-docx-generator = "not-started" +step-5-marking-live-wired = "not-started" +step-6-auth-and-encryption-at-rest = "not-started" +step-7-burrito-release = "not-started" + +[open-prs] +# PR open at end of session, awaiting human decision on merge. +pr-41-branch = "claude/post-phase-1-1-cleanup" +pr-41-title = "post-Phase-1.1 repo tidy + docs taxonomy + wiki staging" +pr-41-content-state = "ready" +pr-41-ci-state = "red (pre-existing failures; see docs/status/ci-state.md)" +pr-41-blocking-on = "human review" + +[ci-state] +# Snapshot at end of session — see docs/status/ci-state.md for detail. +elixir-ci-test = "failure (pre-existing, suspected setup-beam version mismatch)" +rescript-deno-ci-build = "failure (pre-existing, suspected deno fmt on new docs/wiki/ markdown)" +governance-language-package-anti-pattern = "failure (pre-existing, reusable workflow in hyperpolymath/standards)" +all-other-checks = "success" diff --git a/.machine_readable/agent_instructions/debt.a2ml b/.machine_readable/agent_instructions/debt.a2ml index c0238c5..0706bf8 100644 --- a/.machine_readable/agent_instructions/debt.a2ml +++ b/.machine_readable/agent_instructions/debt.a2ml @@ -43,7 +43,7 @@ last-updated = "2026-03-24" # Example: # [[debt.could]] # component = "cicada" -# issue = "RSR_OUTLINE.adoc references banned AGPL-3.0" +# issue = "docs/research/rsr-template.adoc references banned AGPL-3.0" # effort = "easy" # impact = "low" # discovered = "2026-03-23" diff --git a/.machine_readable/svc/k9/examples/setup-repo.k9.ncl b/.machine_readable/svc/k9/examples/setup-repo.k9.ncl index b635d5b..bd2fe19 100644 --- a/.machine_readable/svc/k9/examples/setup-repo.k9.ncl +++ b/.machine_readable/svc/k9/examples/setup-repo.k9.ncl @@ -130,7 +130,7 @@ K9! }, "add-license" = { - description = "Add PMPL-1.0 license", + description = "Add Palimpsest (MPL-2.0) license", commands = [ "curl -sL https://raw.githubusercontent.com/hyperpolymath/pmpl/main/LICENSE -o LICENSE", "echo '✓ License added'", diff --git a/0-AI-MANIFEST.a2ml b/0-AI-MANIFEST.a2ml index 5fb6b70..f1ba558 100644 --- a/0-AI-MANIFEST.a2ml +++ b/0-AI-MANIFEST.a2ml @@ -37,7 +37,7 @@ ".claude/CLAUDE.md" ; Language policy, dev patterns "Justfile" ; Task runner — all commands here "mix.exs" ; Elixir dependencies and config - "llm-warmup-dev.md" ; Developer-oriented LLM briefing + "docs/ai/warmup-dev.md" ; Developer-oriented LLM briefing "QUICKSTART-USER.adoc" ; User setup instructions ) (summary @@ -88,12 +88,11 @@ "must/must.ncl" ; Nickel structural invariants "rescript.json") ; ReScript compiler config (containers - "Containerfile.hardened" ; Production container - "Containerfile.simple" ; Development container - "Containerfile") ; Base container + "Containerfile" ; Primary (development / base) + "Containerfile.hardened") ; Production-hardened variant (packaging "guix.scm" ; GNU Guix (primary) - "flake.nix")) ; Nix (fallback) + "mix.exs")) ; Mix release (fallback) ; ── Critical Invariants ──────────────────────────────────────────── diff --git a/ABI-FFI-README.md b/ABI-FFI-README.md deleted file mode 100644 index f06f72c..0000000 --- a/ABI-FFI-README.md +++ /dev/null @@ -1,385 +0,0 @@ -{{~ Aditionally delete this line and fill out the template below ~}} - -# {{PROJECT}} ABI/FFI Documentation - -## Overview - -This library follows the **Hyperpolymath RSR Standard** for ABI and FFI design: - -- **ABI (Application Binary Interface)** defined in **Idris2** with formal proofs -- **FFI (Foreign Function Interface)** implemented in **Zig** for C compatibility -- **Generated C headers** bridge Idris2 ABI to Zig FFI -- **Any language** can call through standard C ABI - -## Architecture - -``` -┌─────────────────────────────────────────────┐ -│ ABI Definitions (Idris2) │ -│ src/abi/ │ -│ - Types.idr (Type definitions) │ -│ - Layout.idr (Memory layout proofs) │ -│ - Foreign.idr (FFI declarations) │ -└─────────────────┬───────────────────────────┘ - │ - │ generates (at compile time) - ▼ -┌─────────────────────────────────────────────┐ -│ C Headers (auto-generated) │ -│ generated/abi/{{project}}.h │ -└─────────────────┬───────────────────────────┘ - │ - │ imported by - ▼ -┌─────────────────────────────────────────────┐ -│ FFI Implementation (Zig) │ -│ ffi/zig/src/main.zig │ -│ - Implements C-compatible functions │ -│ - Zero-cost abstractions │ -│ - Memory-safe by default │ -└─────────────────┬───────────────────────────┘ - │ - │ compiled to lib{{project}}.so/.a - ▼ -┌─────────────────────────────────────────────┐ -│ Any Language via C ABI │ -│ - Rust, ReScript, Julia, Python, etc. │ -└─────────────────────────────────────────────┘ -``` - -## Directory Structure - -``` -{{project}}/ -├── src/ -│ ├── abi/ # ABI definitions (Idris2) -│ │ ├── Types.idr # Core type definitions with proofs -│ │ ├── Layout.idr # Memory layout verification -│ │ └── Foreign.idr # FFI function declarations -│ └── lib/ # Core library (any language) -│ -├── ffi/ -│ └── zig/ # FFI implementation (Zig) -│ ├── build.zig # Build configuration -│ ├── build.zig.zon # Dependencies -│ ├── src/ -│ │ └── main.zig # C-compatible FFI implementation -│ ├── test/ -│ │ └── integration_test.zig -│ └── include/ -│ └── {{project}}.h # C header (optional, can be generated) -│ -├── generated/ # Auto-generated files -│ └── abi/ -│ └── {{project}}.h # Generated from Idris2 ABI -│ -└── bindings/ # Language-specific wrappers (optional) - ├── rust/ - ├── rescript/ - └── julia/ -``` - -## Why Idris2 for ABI? - -### 1. **Formal Verification** - -Idris2's dependent types allow proving properties about the ABI at compile-time: - -```idris --- Prove struct size is correct -public export -exampleStructSize : HasSize ExampleStruct 16 - --- Prove field alignment is correct -public export -fieldAligned : Divides 8 (offsetOf ExampleStruct.field) - --- Prove ABI is platform-compatible -public export -abiCompatible : Compatible (ABI 1) (ABI 2) -``` - -### 2. **Type Safety** - -Encode invariants that C/Zig cannot express: - -```idris --- Non-null pointer guaranteed at type level -data Handle : Type where - MkHandle : (ptr : Bits64) -> {auto 0 nonNull : So (ptr /= 0)} -> Handle - --- Array with length proof -data Buffer : (n : Nat) -> Type where - MkBuffer : Vect n Byte -> Buffer n -``` - -### 3. **Platform Abstraction** - -Platform-specific types with compile-time selection: - -```idris -CInt : Platform -> Type -CInt Linux = Bits32 -CInt Windows = Bits32 - -CSize : Platform -> Type -CSize Linux = Bits64 -CSize Windows = Bits64 -``` - -### 4. **Safe Evolution** - -Prove that new ABI versions are backward-compatible: - -```idris --- Compiler enforces compatibility -abiUpgrade : ABI 1 -> ABI 2 -abiUpgrade old = MkABI2 { - -- Must preserve all v1 fields - v1_compat = old, - -- Can add new fields - new_features = defaults -} -``` - -## Why Zig for FFI? - -### 1. **C ABI Compatibility** - -Zig exports C-compatible functions naturally: - -```zig -export fn library_function(param: i32) i32 { - return param * 2; -} -``` - -### 2. **Memory Safety** - -Compile-time safety without runtime overhead: - -```zig -// Null check enforced at compile time -const handle = init() orelse return error.InitFailed; -defer free(handle); -``` - -### 3. **Cross-Compilation** - -Built-in cross-compilation to any platform: - -```bash -zig build -Dtarget=x86_64-linux -zig build -Dtarget=aarch64-macos -zig build -Dtarget=x86_64-windows -``` - -### 4. **Zero Dependencies** - -No runtime, no libc required (unless explicitly needed): - -```zig -// Minimal binary size -pub const lib = @import("std"); -// Only includes what you use -``` - -## Building - -### Build FFI Library - -```bash -cd ffi/zig -zig build # Build debug -zig build -Doptimize=ReleaseFast # Build optimized -zig build test # Run tests -``` - -### Generate C Header from Idris2 ABI - -```bash -cd src/abi -idris2 --cg c-header Types.idr -o ../../generated/abi/{{project}}.h -``` - -### Cross-Compile - -```bash -cd ffi/zig - -# Linux x86_64 -zig build -Dtarget=x86_64-linux - -# macOS ARM64 -zig build -Dtarget=aarch64-macos - -# Windows x86_64 -zig build -Dtarget=x86_64-windows -``` - -## Usage - -### From C - -```c -#include "{{project}}.h" - -int main() { - void* handle = {{project}}_init(); - if (!handle) return 1; - - int result = {{project}}_process(handle, 42); - if (result != 0) { - const char* err = {{project}}_last_error(); - fprintf(stderr, "Error: %s\n", err); - } - - {{project}}_free(handle); - return 0; -} -``` - -Compile with: -```bash -gcc -o example example.c -l{{project}} -L./zig-out/lib -``` - -### From Idris2 - -```idris -import {{PROJECT}}.ABI.Foreign - -main : IO () -main = do - Just handle <- init - | Nothing => putStrLn "Failed to initialize" - - Right result <- process handle 42 - | Left err => putStrLn $ "Error: " ++ errorDescription err - - free handle - putStrLn "Success" -``` - -### From Rust - -```rust -#[link(name = "{{project}}")] -extern "C" { - fn {{project}}_init() -> *mut std::ffi::c_void; - fn {{project}}_free(handle: *mut std::ffi::c_void); - fn {{project}}_process(handle: *mut std::ffi::c_void, input: u32) -> i32; -} - -fn main() { - unsafe { - let handle = {{project}}_init(); - assert!(!handle.is_null()); - - let result = {{project}}_process(handle, 42); - assert_eq!(result, 0); - - {{project}}_free(handle); - } -} -``` - -### From Julia - -```julia -const lib{{project}} = "lib{{project}}" - -function init() - handle = ccall((:{{project}}_init, lib{{project}}), Ptr{Cvoid}, ()) - handle == C_NULL && error("Failed to initialize") - handle -end - -function process(handle, input) - result = ccall((:{{project}}_process, lib{{project}}), Cint, (Ptr{Cvoid}, UInt32), handle, input) - result -end - -function cleanup(handle) - ccall((:{{project}}_free, lib{{project}}), Cvoid, (Ptr{Cvoid},), handle) -end - -# Usage -handle = init() -try - result = process(handle, 42) - println("Result: $result") -finally - cleanup(handle) -end -``` - -## Testing - -### Unit Tests (Zig) - -```bash -cd ffi/zig -zig build test -``` - -### Integration Tests - -```bash -cd ffi/zig -zig build test-integration -``` - -### ABI Verification (Idris2) - -```idris --- Compile-time verification -%runElab verifyABI - --- Runtime checks -main : IO () -main = do - verifyLayoutsCorrect - verifyAlignmentsCorrect - putStrLn "ABI verification passed" -``` - -## Contributing - -When modifying the ABI/FFI: - -1. **Update ABI first** (`src/abi/*.idr`) - - Modify type definitions - - Update proofs - - Ensure backward compatibility - -2. **Generate C header** - ```bash - idris2 --cg c-header src/abi/Types.idr -o generated/abi/{{project}}.h - ``` - -3. **Update FFI implementation** (`ffi/zig/src/main.zig`) - - Implement new functions - - Match ABI types exactly - -4. **Add tests** - - Unit tests in Zig - - Integration tests - - ABI verification tests - -5. **Update documentation** - - Function signatures - - Usage examples - - Migration guide (if breaking changes) - -## License - -MPL-2.0 - -## See Also - -- [Idris2 Documentation](https://idris2.readthedocs.io) -- [Zig Documentation](https://ziglang.org/documentation/master/) -- [Rhodium Standard Repositories](https://github.com/hyperpolymath/rhodium-standard-repositories) -- [FFI Migration Guide](../ffi-migration-guide.md) -- [ABI Migration Guide](../abi-migration-guide.md) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index b6dacab..22e7543 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,56 +1,78 @@ - - - +// SPDX-License-Identifier: MPL-2.0 = Changelog +:toc: All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The format is based on https://keepachangelog.com/en/1.1.0/[Keep a Changelog], +and this project adheres to https://semver.org/spec/v2.0.0.html[Semantic Versioning]. == [Unreleased] === Added -- RSR Gold compliance documentation -- Containerfile with Chainguard Wolfi base -- Architecture documentation (MAA/RMR/RMO) -- TPCF contribution framework - -=== Removed -- Nix flakes (replaced by Guix manifest; see `guix.scm`) - -== [2.0.0] - 2024-12-01 -=== Added -- Complete rewrite from Java to Elixir/Phoenix -- Phoenix LiveView UI for real-time marking -- CubDB embedded database (replaces file-based storage) -- File system watcher for automatic ingestion -- Burrito cross-platform packaging -- WASM plugin support (optional) -- Post-quantum cryptography support (optional) +* `docs/README.adoc` — guided index of the documentation tree. +* `RSR_COMPLIANCE.adoc` — explicit compliance tracker against the + Rhodium Standard Repository spec. +* `docs/` taxonomy: `ai/`, `examples/`, `operations/`, `research/`, + `sessions/`, `specs/`, `status/`. +* CubDB-backed persistence layer (`EtmaHandler.Repo`) — Phase 1.1 of + the v1 critical path. +* RSR Gold compliance documentation +* Containerfile.hardened with Chainguard Wolfi base +* Architecture documentation (MAA / RMR / RMO) +* TPCF contribution framework === Changed -- Architecture: Monolithic Java → OTP supervision trees -- Storage: File-based → CubDB append-only B-tree -- UI: Desktop Java Swing → Web-based LiveView -- Packaging: JAR/installer → Single binary (Burrito) + +* Repository layout reorganised. Top-level reduced from ~28 free-form + docs to a focused set of community files plus the v1-critical pair + (`ROADMAP.adoc`, `TOPOLOGY.md`). All other long-form documents now + live under `docs//`. +* `EtmaHandler.Bouncer` — broken `init/1` (referenced undefined + symbols, invalid struct-literal syntax) replaced with a + loud-fail stub. Module constants exposed as zero-arity functions. +* `README.adoc` — license section updated to the post-migration + wording (Palimpsest License (MPL-2.0)); duplicate Architecture + section removed; broken `CONTRIBUTING.adoc` link fixed. === Removed -- Java codebase -- External database dependencies -- Platform-specific installers -== [1.0.0] - 2023-01-01 +* `CHANGELOG.md`, `CODE_OF_CONDUCT.md`, `MAINTAINERS.md` — duplicates + of the canonical `.adoc` versions. +* `ABI-FFI-README.md` — unfilled template (still contained literal + `{{PROJECT}}` placeholder). +* `Containerfile.simple` — unused; the Containerfile pair is + `Containerfile` (dev/base) and `Containerfile.hardened` (prod). +* `well-known-template/` and `well-known-template.tar.gz` — RSR + template scaffolding redundant with the populated `.well-known/`. +* `schemas/config.cue` — CUE is prohibited by the language policy. +* Duplicate root `FUNDING.yml`; the canonical one is + `.github/FUNDING.yml`. +* `LICENSES/PMPL-1.0.txt`, `LICENSES/PMPL-1.0-or-later.txt` — the + Palimpsest text now lives in `LICENSES/MPL-2.0.txt` per the + SPDX-MPL-2.0 identifier the project uses. +* `flake.nix`, `flake.lock` (replaced by Guix manifest; see + `guix.scm`). -=== Added -- Initial Java implementation -- Basic marking functionality -- .fhi file parsing -- .docx export +=== Fixed + +* Four SPDX-License-Identifier headers still carrying `PMPL-1.0` + after the migration to MPL-2.0: three workflows (CodeQL, + secret-scanner, scorecard) and + `lib/etma_handler/proven/safe_state_machine.ex`. +* README licence shield: `PMPL-1.0` → `MPL-2.0`. +* `docs/research/palimpsest.adoc` rewritten to describe the + post-migration state (Palimpsest is MPL-2.0 in SPDX terms). +* SPDX header added to `docs/examples/nickel-config-example.ncl` + (consequence of moving the file out of the old `configs/` dir; + Hypatia bot flagged the missing header on PR #41). ---- +== Earlier history -[Unreleased]: https://github.com/your-org/tma-mark2/compare/v2.0.0...HEAD -[2.0.0]: https://github.com/your-org/tma-mark2/compare/v1.0.0...v2.0.0 -[1.0.0]: https://github.com/your-org/tma-mark2/releases/tag/v1.0.0 +This project is currently at `0.1.0-alpha`; no formal release has been +cut. The repository started as scaffolding around a planned BEAM +edition of the Open University's electronic Tutor-Marked Assignment +(eTMA) marking tool, originally written in Java. See +link:README.adoc[README.adoc] for the project intent and +link:TOPOLOGY.md[TOPOLOGY.md] for honest current state. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index ab60a7a..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,56 +0,0 @@ - - - -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -### Added -- RSR Gold compliance documentation -- Containerfile with Chainguard Wolfi base -- Architecture documentation (MAA/RMR/RMO) -- TPCF contribution framework - -### Removed -- Nix flakes (replaced by Guix manifest; see `guix.scm`) - -## [2.0.0] - 2024-12-01 - -### Added -- Complete rewrite from Java to Elixir/Phoenix -- Phoenix LiveView UI for real-time marking -- CubDB embedded database (replaces file-based storage) -- File system watcher for automatic ingestion -- Burrito cross-platform packaging -- WASM plugin support (optional) -- Post-quantum cryptography support (optional) - -### Changed -- Architecture: Monolithic Java → OTP supervision trees -- Storage: File-based → CubDB append-only B-tree -- UI: Desktop Java Swing → Web-based LiveView -- Packaging: JAR/installer → Single binary (Burrito) - -### Removed -- Java codebase -- External database dependencies -- Platform-specific installers - -## [1.0.0] - 2023-01-01 - -### Added -- Initial Java implementation -- Basic marking functionality -- .fhi file parsing -- .docx export - ---- - -[Unreleased]: https://github.com/your-org/tma-mark2/compare/v2.0.0...HEAD -[2.0.0]: https://github.com/your-org/tma-mark2/compare/v1.0.0...v2.0.0 -[1.0.0]: https://github.com/your-org/tma-mark2/releases/tag/v1.0.0 diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc index 5acf869..fadd4eb 100644 --- a/CODE_OF_CONDUCT.adoc +++ b/CODE_OF_CONDUCT.adoc @@ -54,7 +54,7 @@ an individual is officially representing the community in public spaces. == Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement (see MAINTAINERS.md). +reported to the community leaders responsible for enforcement (see MAINTAINERS.adoc). All complaints will be reviewed and investigated promptly and fairly. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 1f1548c..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,27 +0,0 @@ - -# Contributor Covenant Code of Conduct - -## Our Pledge - -We pledge to make participation a harassment-free experience for everyone. - -## Our Standards - -**Positive behavior:** -* Using welcoming language -* Being respectful of differing viewpoints -* Accepting constructive criticism -* Focusing on what is best for the community - -**Unacceptable behavior:** -* Harassment, trolling, or personal attacks -* Publishing private information without permission - -## Enforcement - -Report issues to the maintainers. All complaints will be reviewed. - -## Attribution - -Adapted from [Contributor Covenant](https://www.contributor-covenant.org/) v2.1. - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 04649a2..1ee97fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,17 +31,17 @@ tma-mark2/ │ └── proposals/ # RFCs (Perimeter 3) ├── examples/ # Examples (Perimeter 3) ├── spec/ # Spec tests (Perimeter 3) -├── tests/ # Test suite (Perimeter 2-3) +├── test/ # Test suite — Elixir convention (Perimeter 2-3) ├── .well-known/ # Protocol files (Perimeter 1-3) ├── .github/ # GitHub config (Perimeter 1) │ ├── ISSUE_TEMPLATE/ │ └── workflows/ -├── CHANGELOG.md -├── CODE_OF_CONDUCT.md +├── CHANGELOG.adoc +├── CODE_OF_CONDUCT.adoc ├── CONTRIBUTING.md # This file -├── GOVERNANCE.md +├── GOVERNANCE.adoc ├── LICENSE -├── MAINTAINERS.md +├── MAINTAINERS.adoc ├── README.adoc ├── SECURITY.md ├── guix.scm # Guix manifest (Perimeter 1) diff --git a/Containerfile.simple b/Containerfile.simple deleted file mode 100644 index 77faf48..0000000 --- a/Containerfile.simple +++ /dev/null @@ -1,66 +0,0 @@ -# SPDX-FileCopyrightText: 2024 eTMA Handler Contributors -# SPDX-License-Identifier: MIT - -# eTMA Handler - Simple Containerfile -# Uses official Elixir image for easier builds - -# ============================================================================= -# Stage 1: Build -# ============================================================================= -FROM docker.io/elixir:1.16-alpine AS builder - -# Install build deps -RUN apk add --no-cache build-base git nodejs npm - -ENV MIX_ENV=prod - -WORKDIR /app - -# Install hex and rebar -RUN mix local.hex --force && mix local.rebar --force - -# Copy deps first for caching -COPY mix.exs mix.lock ./ -COPY config config -RUN mix deps.get --only prod && mix deps.compile - -# Copy assets and build -COPY assets assets -COPY priv priv -RUN mix assets.deploy || true - -# Copy source and compile -COPY lib lib -RUN mix compile - -# Build release -RUN mix release - -# ============================================================================= -# Stage 2: Runtime -# ============================================================================= -FROM docker.io/alpine:3.19 - -RUN apk add --no-cache libstdc++ ncurses-libs openssl - -# Create user -RUN addgroup -g 1000 etma && adduser -u 1000 -G etma -h /app -D etma - -WORKDIR /app - -# Copy release -COPY --from=builder --chown=etma:etma /app/_build/prod/rel/etma_handler ./ - -# Data dir -RUN mkdir -p /data && chown etma:etma /data - -USER etma - -ENV PHX_HOST=0.0.0.0 \ - PHX_PORT=4000 \ - ETMA_DATA_DIR=/data - -EXPOSE 4000 -VOLUME ["/data"] - -CMD ["bin/etma_handler", "start"] diff --git a/FUNDING.yml b/FUNDING.yml deleted file mode 100644 index 4ab2b3c..0000000 --- a/FUNDING.yml +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-FileCopyrightText: 2024 eTMA Handler Contributors -# SPDX-License-Identifier: MPL-2.0 - -# Funding sources for eTMA Handler -# These are shown on the GitHub Sponsors button - -github: [] -patreon: -open_collective: -ko_fi: -tidelift: -community_bridge: -liberapay: -issuehunt: -otechie: -lfx_crowdfunding: -custom: [] diff --git a/GOVERNANCE.adoc b/GOVERNANCE.adoc index dc82826..e5ed388 100644 --- a/GOVERNANCE.adoc +++ b/GOVERNANCE.adoc @@ -23,7 +23,7 @@ The BDFL has final authority on project decisions: === Core Team -Core team members (see MAINTAINERS.md): +Core team members (see MAINTAINERS.adoc): * Merge permissions * Release management diff --git a/Justfile b/Justfile index 4df9fb2..3593e09 100644 --- a/Justfile +++ b/Justfile @@ -103,7 +103,7 @@ rescript-watch: # AffineScript build affine: @echo ">>> Building AffineScript frontend" - ./build-affine.sh + ./experiments/affine-frontend/build.sh # AffineScript watch mode affine-watch: @@ -546,7 +546,7 @@ help-me: echo " just heal (auto-fix)" echo "Common issues: CubDB lock, missing Rust, port 4000 in use." ;; 6) echo ""; echo "Run: just tour (guided walkthrough)" - echo "Read: README.adoc, EXPLAINME.adoc, llm-warmup-dev.md" ;; + echo "Read: README.adoc, EXPLAINME.adoc, docs/ai/warmup-dev.md" ;; 7) echo ""; echo "Run: just security-audit (dep audit + Trivy)" echo " just assail (panic-attacker scan)" echo " just sbom-generate (SBOM)" ;; diff --git a/LICENSES/PMPL-1.0-or-later.txt b/LICENSES/PMPL-1.0-or-later.txt deleted file mode 100644 index 711e372..0000000 --- a/LICENSES/PMPL-1.0-or-later.txt +++ /dev/null @@ -1,162 +0,0 @@ -SPDX-License-Identifier: MPL-2.0 -SPDX-FileCopyrightText: 2025 Palimpsest Stewardship Council - -================================================================================ -PALIMPSEST-MPL LICENSE VERSION 1.0 -================================================================================ - -File-level copyleft with ethical use and quantum-safe provenance - -Based on Mozilla Public License 2.0 - --------------------------------------------------------------------------------- -PREAMBLE --------------------------------------------------------------------------------- - -This License extends the Mozilla Public License 2.0 (MPL-2.0) with provisions -for ethical use, post-quantum cryptographic provenance, and emotional lineage -protection. The base MPL-2.0 terms apply except where explicitly modified by -the Exhibits below. - -Like a palimpsest manuscript where each layer builds upon what came before, -this license recognizes that creative works carry history, context, and meaning -that transcend mere code or text. - --------------------------------------------------------------------------------- -SECTION 1: BASE LICENSE --------------------------------------------------------------------------------- - -This License incorporates the full text of Mozilla Public License 2.0 by -reference. The complete MPL-2.0 text is available at: -https://www.mozilla.org/en-US/MPL/2.0/ - -All terms, conditions, and definitions from MPL-2.0 apply except where -explicitly modified by the Exhibits in this License. - --------------------------------------------------------------------------------- -SECTION 2: ADDITIONAL DEFINITIONS --------------------------------------------------------------------------------- - -2.1. "Emotional Lineage" - means the narrative, cultural, symbolic, and contextual meaning embedded - in Covered Software, including but not limited to: protest traditions, - cultural heritage, trauma narratives, and community stories. - -2.2. "Provenance Metadata" - means cryptographically signed attribution information attached to or - associated with Covered Software, including author identities, timestamps, - modification history, and lineage references. - -2.3. "Non-Interpretive System" - means any automated system that processes Covered Software without - preserving or considering its Emotional Lineage, including but not - limited to: AI training pipelines, content aggregators, and automated - summarization tools. - -2.4. "Quantum-Safe Signature" - means a cryptographic signature using algorithms resistant to attacks - by quantum computers, as specified in Exhibit B. - --------------------------------------------------------------------------------- -SECTION 3: ETHICAL USE REQUIREMENTS --------------------------------------------------------------------------------- - -In addition to the rights and obligations under MPL-2.0: - -3.1. Emotional Lineage Preservation - You must make reasonable efforts to preserve and communicate the - Emotional Lineage of Covered Software when distributing or creating - derivative works. This includes maintaining narrative context, cultural - attributions, and symbolic meaning where documented. - -3.2. Non-Interpretive System Notice - If You use Covered Software as input to a Non-Interpretive System, You - must: - (a) document such use in a publicly accessible manner; and - (b) not claim that outputs of such systems carry the Emotional Lineage - of the original work without explicit permission from Contributors. - -3.3. Ethical Use Declaration - Commercial use of Covered Software requires acknowledgment that You have - read and understood Exhibit A (Ethical Use Guidelines) and agree to act - in good faith accordance with its principles. - -See Exhibit A for complete Ethical Use Guidelines. - --------------------------------------------------------------------------------- -SECTION 4: PROVENANCE REQUIREMENTS --------------------------------------------------------------------------------- - -4.1. Metadata Preservation - You must not strip, alter, or obscure Provenance Metadata from Covered - Software except where technically necessary and with clear documentation - of any changes. - -4.2. Quantum-Safe Provenance (Optional) - Contributors may sign their Contributions using Quantum-Safe Signatures. - If Quantum-Safe Signatures are present, You must preserve them in all - distributions. - -4.3. Lineage Chain - When creating derivative works, You should extend the provenance chain - to include Your own contributions, maintaining cryptographic linkage to - prior Contributors where feasible. - -See Exhibit B for Quantum-Safe Provenance specifications. - --------------------------------------------------------------------------------- -SECTION 5: GOVERNANCE --------------------------------------------------------------------------------- - -5.1. Stewardship Council - This License is maintained by the Palimpsest Stewardship Council, which - may issue clarifications, interpretive guidance, and future versions. - -5.2. Version Selection - You may use Covered Software under this version of the License or any - later version published by the Palimpsest Stewardship Council. - -5.3. Dispute Resolution - Disputes regarding interpretation of Ethical Use Requirements (Section 3) - should first be submitted to the Palimpsest Stewardship Council for - non-binding guidance before pursuing legal remedies. - --------------------------------------------------------------------------------- -SECTION 6: COMPATIBILITY --------------------------------------------------------------------------------- - -6.1. MPL-2.0 Compatibility - Covered Software under this License may be combined with software under - MPL-2.0. The combined work must comply with both licenses. - -6.2. Secondary Licenses - The Secondary License provisions of MPL-2.0 Section 3.3 apply to this - License. - --------------------------------------------------------------------------------- -EXHIBITS --------------------------------------------------------------------------------- - -Exhibit A - Ethical Use Guidelines -Exhibit B - Quantum-Safe Provenance Specification - -See separate files: -- EXHIBIT-A-ETHICAL-USE.txt -- EXHIBIT-B-QUANTUM-SAFE.txt - --------------------------------------------------------------------------------- -END OF PALIMPSEST-MPL-1.0 LICENSE TEXT --------------------------------------------------------------------------------- - -For exhibits, specifications, provenance rules, and governance: -https://github.com/hyperpolymath/palimpsest-license - -For legal frameworks and jurisdictional analysis: -See /legal/frameworks/ - -For provenance and audit tooling: -See /tools/ and /spec/PROVENANCE-SPEC.adoc - -For questions about this License: -- Repository: https://github.com/hyperpolymath/palimpsest-license -- Council: contact via repository Issues diff --git a/LICENSES/PMPL-1.0.txt b/LICENSES/PMPL-1.0.txt deleted file mode 100644 index ec540b3..0000000 --- a/LICENSES/PMPL-1.0.txt +++ /dev/null @@ -1,153 +0,0 @@ -SPDX-License-Identifier: MPL-2.0 -SPDX-FileCopyrightText: 2024-2025 Palimpsest Stewardship Council - -================================================================================ -PALIMPSEST-MPL LICENSE VERSION 1.0 -================================================================================ - -File-level copyleft with ethical use and quantum-safe provenance - -Based on Mozilla Public License 2.0 - --------------------------------------------------------------------------------- -PREAMBLE --------------------------------------------------------------------------------- - -This License extends the Mozilla Public License 2.0 (MPL-2.0) with provisions -for ethical use, post-quantum cryptographic provenance, and emotional lineage -protection. The base MPL-2.0 terms apply except where explicitly modified by -the Exhibits below. - -Like a palimpsest manuscript where each layer builds upon what came before, -this license recognizes that creative works carry history, context, and meaning -that transcend mere code or text. - --------------------------------------------------------------------------------- -SECTION 1: BASE LICENSE --------------------------------------------------------------------------------- - -This License incorporates the full text of Mozilla Public License 2.0 by -reference. The complete MPL-2.0 text is available at: -https://www.mozilla.org/en-US/MPL/2.0/ - -All terms, conditions, and definitions from MPL-2.0 apply except where -explicitly modified by the Exhibits in this License. - --------------------------------------------------------------------------------- -SECTION 2: ADDITIONAL DEFINITIONS --------------------------------------------------------------------------------- - -2.1. "Emotional Lineage" - means the narrative, cultural, symbolic, and contextual meaning embedded - in Covered Software, including but not limited to: protest traditions, - cultural heritage, trauma narratives, and community stories. - -2.2. "Provenance Metadata" - means cryptographically signed attribution information attached to or - associated with Covered Software, including author identities, timestamps, - modification history, and lineage references. - -2.3. "Non-Interpretive System" - means any automated system that processes Covered Software without - preserving or considering its Emotional Lineage, including but not - limited to: AI training pipelines, content aggregators, and automated - summarization tools. - -2.4. "Quantum-Safe Signature" - means a cryptographic signature using algorithms resistant to attacks - by quantum computers, as specified in Exhibit B. - --------------------------------------------------------------------------------- -SECTION 3: ETHICAL USE REQUIREMENTS --------------------------------------------------------------------------------- - -In addition to the rights and obligations under MPL-2.0: - -3.1. Emotional Lineage Preservation - You must make reasonable efforts to preserve and communicate the - Emotional Lineage of Covered Software when distributing or creating - derivative works. This includes maintaining narrative context, cultural - attributions, and symbolic meaning where documented. - -3.2. Non-Interpretive System Notice - If You use Covered Software as input to a Non-Interpretive System, You - must: - (a) document such use in a publicly accessible manner; and - (b) not claim that outputs of such systems carry the Emotional Lineage - of the original work without explicit permission from Contributors. - -3.3. Ethical Use Declaration - Commercial use of Covered Software requires acknowledgment that You have - read and understood Exhibit A (Ethical Use Guidelines) and agree to act - in good faith accordance with its principles. - -See Exhibit A for complete Ethical Use Guidelines. - --------------------------------------------------------------------------------- -SECTION 4: PROVENANCE REQUIREMENTS --------------------------------------------------------------------------------- - -4.1. Metadata Preservation - You must not strip, alter, or obscure Provenance Metadata from Covered - Software except where technically necessary and with clear documentation - of any changes. - -4.2. Quantum-Safe Provenance (Optional) - Contributors may sign their Contributions using Quantum-Safe Signatures. - If Quantum-Safe Signatures are present, You must preserve them in all - distributions. - -4.3. Lineage Chain - When creating derivative works, You should extend the provenance chain - to include Your own contributions, maintaining cryptographic linkage to - prior Contributors where feasible. - -See Exhibit B for Quantum-Safe Provenance specifications. - --------------------------------------------------------------------------------- -SECTION 5: GOVERNANCE --------------------------------------------------------------------------------- - -5.1. Stewardship Council - This License is maintained by the Palimpsest Stewardship Council, which - may issue clarifications, interpretive guidance, and future versions. - -5.2. Version Selection - You may use Covered Software under this version of the License or any - later version published by the Palimpsest Stewardship Council. - -5.3. Dispute Resolution - Disputes regarding interpretation of Ethical Use Requirements (Section 3) - should first be submitted to the Palimpsest Stewardship Council for - non-binding guidance before pursuing legal remedies. - --------------------------------------------------------------------------------- -SECTION 6: COMPATIBILITY --------------------------------------------------------------------------------- - -6.1. MPL-2.0 Compatibility - Covered Software under this License may be combined with software under - MPL-2.0. The combined work must comply with both licenses. - -6.2. Secondary Licenses - The Secondary License provisions of MPL-2.0 Section 3.3 apply to this - License. - --------------------------------------------------------------------------------- -EXHIBITS --------------------------------------------------------------------------------- - -Exhibit A - Ethical Use Guidelines -Exhibit B - Quantum-Safe Provenance Specification - -See separate files: -- EXHIBIT-A-ETHICAL-USE.txt -- EXHIBIT-B-QUANTUM-SAFE.txt - --------------------------------------------------------------------------------- -END OF PALIMPSEST-MPL LICENSE VERSION 1.0 --------------------------------------------------------------------------------- - -For questions about this License: -- Repository: https://github.com/hyperpolymath/palimpsest-license -- Council: contact via repository Issues diff --git a/licenses/MPL-2.0-NL.txt b/LICENSES/translations/MPL-2.0-NL.txt similarity index 100% rename from licenses/MPL-2.0-NL.txt rename to LICENSES/translations/MPL-2.0-NL.txt diff --git a/licenses/PALIMPSEST-EN.txt b/LICENSES/translations/PALIMPSEST-EN.txt similarity index 100% rename from licenses/PALIMPSEST-EN.txt rename to LICENSES/translations/PALIMPSEST-EN.txt diff --git a/licenses/PALIMPSEST-NL.txt b/LICENSES/translations/PALIMPSEST-NL.txt similarity index 100% rename from licenses/PALIMPSEST-NL.txt rename to LICENSES/translations/PALIMPSEST-NL.txt diff --git a/MAINTAINERS.md b/MAINTAINERS.md deleted file mode 100644 index a51aeb0..0000000 --- a/MAINTAINERS.md +++ /dev/null @@ -1,59 +0,0 @@ - - - -# Maintainers - -This file lists the maintainers of the eTMA Handler project. - -## Current Maintainers - -### BDFL - -| Name | GitHub | Role | Since | -|------|--------|------|-------| -| TBD | @tbd | Project Lead | 2024 | - -### Core Team - -| Name | GitHub | Area | Since | -|------|--------|------|-------| -| TBD | @tbd | Core | 2024 | - -## Emeritus - -Former maintainers who have moved on: - -| Name | GitHub | Role | Period | -|------|--------|------|--------| -| - | - | - | - | - -## Responsibilities - -### All Maintainers - -- Follow Code of Conduct -- Review PRs in timely manner -- Respond to security reports per SLA -- Maintain documentation -- Mentor contributors - -### BDFL Additional - -- Final decision authority -- Succession planning -- Core team appointments -- Project direction - -## Contact - -- **Security issues**: See SECURITY.md (do not open public issues) -- **General questions**: GitHub Discussions -- **Bugs/Features**: GitHub Issues - -## Becoming a Maintainer - -See CONTRIBUTING.adoc for the TPCF pathway from Perimeter 3 → 2 → 1. - ---- - -Last updated: 2024-12-01 diff --git a/PALIMPSEST.adoc b/PALIMPSEST.adoc deleted file mode 100644 index ebaa6d0..0000000 --- a/PALIMPSEST.adoc +++ /dev/null @@ -1,41 +0,0 @@ -= Palimpsest License -:toc: -:toc-placement!: - -image:https://img.shields.io/badge/License-PMPL--1.0-blue.svg[License: PMPL-1.0,link="https://github.com/hyperpolymath/palimpsest-license"] -image:https://img.shields.io/badge/Philosophy-Palimpsest-indigo.svg[Palimpsest,link="https://github.com/hyperpolymath/palimpsest-license"] - -toc::[] - -== Legal Status - -This project is licensed under the **Palimpsest-MPL License 1.0 (PMPL-1.0)**. -For SPDX and tooling, use **MPL-2.0**. - -PMPL-1.0 incorporates the Mozilla Public License 2.0 by reference and adds -ethical-use, provenance, and lineage requirements. - -== What PMPL Adds - -* **Emotional Lineage** - preserve narrative intent and cultural context -* **Provenance Integrity** - retain attribution and lineage metadata -* **Ethical Use Constraints** - explicit consent for non-interpretive AI training -* **Quantum-Safe Provenance (optional)** - post-quantum signature support - -== How to Adopt - -1. Include the PMPL-1.0 license text in `LICENSE`. -2. Add SPDX headers to source files: - `SPDX-License-Identifier: MPL-2.0` -3. Add a Palimpsest badge to your README (see `assets/badges/` and `embed/license-blocks/`). - -== Versioning - -See `VERSIONING.adoc` for the release process and the "-or-later" model. -The current legal text is PMPL-1.0. - -== References - -* `legal/README.adoc` -* `assets/badges/README.md` -* `embed/license-blocks/README.md` diff --git a/QUICKSTART-MAINTAINER.adoc b/QUICKSTART-MAINTAINER.adoc index bc41e3a..076c28a 100644 --- a/QUICKSTART-MAINTAINER.adoc +++ b/QUICKSTART-MAINTAINER.adoc @@ -23,7 +23,7 @@ Key workflows: == Releasing 1. Update version in project config -2. Update CHANGELOG.md +2. Update CHANGELOG.adoc 3. Tag: `git tag -s v` 4. Push: `git push origin main --tags` diff --git a/README.adoc b/README.adoc index b0e58c1..50955f6 100644 --- a/README.adoc +++ b/README.adoc @@ -1,4 +1,4 @@ -image:https://img.shields.io/badge/License-PMPL--1.0-blue.svg[License: PMPL-1.0,link="https://github.com/hyperpolymath/palimpsest-license"] +image:https://img.shields.io/badge/License-MPL--2.0-blue.svg[License: MPL-2.0,link="https://github.com/hyperpolymath/palimpsest-license"] // SPDX-License-Identifier: MPL-2.0 // SPDX-FileCopyrightText: 2025 Jonathan D.A. Jewell @@ -17,7 +17,9 @@ image:https://img.shields.io/badge/OTP-26+-red[OTP Version] == Status -**This is an early-stage scaffold, not a working application.** A Phoenix shell, the Rust crypto/NLP NIFs, and the marking calculator are real. The data plane (CubDB Repo, FHI parser, file watcher, `.docx` generator) is unimplemented. Marking-analytics modules are docstring stubs. See link:TOPOLOGY.md[TOPOLOGY.md] for an honest component-by-component status, and link:ROADMAP.adoc[ROADMAP.adoc] for the path to v1. +**This is an early-stage scaffold, not a working application.** A Phoenix shell, the Rust crypto/NLP NIFs, the CubDB-backed Repo, and the marking calculator are real. The rest of the data plane (FHI parser, file watcher, `.docx` generator) is unimplemented. Marking-analytics modules are docstring stubs. See link:TOPOLOGY.md[TOPOLOGY.md] for an honest component-by-component status, and link:ROADMAP.adoc[ROADMAP.adoc] for the path to v1. + +For a guided tour of the repository, see link:docs/README.adoc[docs/README.adoc]. For RSR compliance state, see link:RSR_COMPLIANCE.adoc[RSR_COMPLIANCE.adoc]. == Overview @@ -106,7 +108,7 @@ Then open http://localhost:4000 in your browser. |=== |Component |Technology -|Language |Elixir 1.14+ / OTP 25+ +|Language |Elixir 1.18+ / OTP 25 (pinned via `.tool-versions`) |Web Framework |Phoenix 1.7 + LiveView |HTTP Server |Bandit |Database |CubDB (embedded) @@ -242,11 +244,14 @@ podman run -p 4000:4000 -v ~/assignments:/data etma-handler:latest == Contributing -See link:CONTRIBUTING.adoc[CONTRIBUTING.adoc] for guidelines. +See link:CONTRIBUTING.md[CONTRIBUTING.md] for guidelines, and link:GOVERNANCE.adoc[GOVERNANCE.adoc] for the decision-making model. == License -Palimpsest-MPL-1.0 License - see link:LICENSE.txt[LICENSE.txt] for details. +Palimpsest License (MPL-2.0) — see link:LICENSE[LICENSE] for the +binding text and link:NOTICE[NOTICE] for the Palimpsest disposition. +The philosophy is documented in +link:docs/research/palimpsest.adoc[docs/research/palimpsest.adoc]. == Security @@ -258,8 +263,3 @@ See link:SECURITY.md[SECURITY.md] for security policies and vulnerability report * The Elixir and Phoenix communities * CubDB for the excellent embedded database * Burrito for cross-platform packaging - - -== Architecture - -See link:TOPOLOGY.md[TOPOLOGY.md] for a visual architecture map and completion dashboard. diff --git a/ROADMAP.adoc b/ROADMAP.adoc index b319258..2c26af3 100644 --- a/ROADMAP.adoc +++ b/ROADMAP.adoc @@ -49,7 +49,7 @@ Goal: docs match reality so the rest of planning isn't fiction. * [ ] `mix.exs` version → `0.1.0-alpha` * [ ] Rewrite `TOPOLOGY.md` dashboard with real percentages * [ ] Rewrite `ROADMAP.adoc` (this file) -* [ ] Update `TEST-NEEDS.md` to reflect 4 real test files +* [ ] Update `docs/status/test-needs.md` to reflect 4 real test files * [ ] Move clearly-deferred experiments out of the primary tree (`experiments/` for mobile, AffineScript, Bebop, Zig) **Exit criteria:** a new reader can tell what works in 5 minutes. diff --git a/RSR_COMPLIANCE.adoc b/RSR_COMPLIANCE.adoc new file mode 100644 index 0000000..31c5630 --- /dev/null +++ b/RSR_COMPLIANCE.adoc @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MPL-2.0 += tma-mark2 — RSR Compliance Tracker +:toc: +:sectnums: + +This file tracks this project's compliance with the **Rhodium Standard +Repository (RSR)** specification. For the template itself (canonical +directory layout, recipe set, etc.) see +link:docs/research/rsr-template.adoc[docs/research/rsr-template.adoc]. + +== Compliance summary + +|=== +| Tier | Status + +| RSR Required files | ✓ pass +| Language policy | ✓ pass (Elixir tier 1; ReScript planned) +| Build system | ✓ pass (Guix primary, Mix fallback) +| Container | ✓ pass (Containerfile + hardened variant) +| Well-known metadata | ✓ pass (.well-known/ populated) +| License + SPDX | ✓ pass (MPL-2.0 across the tree) +| Documentation taxonomy | ✓ pass (docs/{architecture,specs,…}) +| State tracking | partial (uses .machine_readable/6a2/STATE.a2ml + rather than root-level STATE.scm) +|=== + +== Required files + +[cols="2,1,3"] +|=== +| Path | Present | Notes + +| `.editorconfig` | ✓ | +| `.gitignore` | ✓ | +| `.gitattributes` | ✓ | +| `.tool-versions` | ✓ | Elixir 1.18.4-otp-25 +| `Justfile` | ✓ | +| `README.adoc` | ✓ | +| `CHANGELOG.adoc` | ✓ | +| `CONTRIBUTING.md` | ✓ | +| `CODE_OF_CONDUCT.adoc` | ✓ | +| `GOVERNANCE.adoc` | ✓ | +| `MAINTAINERS.adoc` | ✓ | +| `SECURITY.md` | ✓ | +| `LICENSE` | ✓ | Standard MPL-2.0 for tooling +| `NOTICE` | ✓ | Palimpsest disposition +| `LICENSES/MPL-2.0.txt` | ✓ | Palimpsest text +| `RSR_COMPLIANCE.adoc` | ✓ | This file +| `.well-known/security.txt` | ✓ | +| `.well-known/ai.txt` | ✓ | +| `.well-known/humans.txt` | ✓ | +| `guix.scm` | ✓ | +|=== + +== Language policy + +This project uses only languages on the Hyperpolymath allowlist +(see link:.claude/CLAUDE.md[.claude/CLAUDE.md]): + +[cols="2,1,3"] +|=== +| Language | Use | Status + +| Elixir / Erlang | Application core, Phoenix web layer | active +| Rust | NIFs (`native/`) — tma_crypto, tma_nlp | active +| ReScript | Frontend (planned; not yet wired) | planned +| Nickel | Structural contracts (`must/`) | active +| Guile Scheme | State / meta (`.machine_readable/`) | active +| Bash | `setup.sh`, scripts | active +|=== + +No TypeScript, Node, Python, Go, Kotlin, Swift, or Flutter. + +== Build system + +Primary: link:guix.scm[guix.scm] (full reproducibility, Guix store +output). + +Fallback: `mix release` for environments without Guix. + +The `Justfile` cascade auto-selects: + +[source] +---- +if guix available && guix.scm exists: + guix build +else: + mix release +---- + +See link:docs/status/seams-review.adoc[docs/status/seams-review.adoc] +for the SEAMS review of the build system. + +== Container strategy + +Two Containerfiles: + +* link:Containerfile[Containerfile] — dev / base image. +* link:Containerfile.hardened[Containerfile.hardened] — production + variant with Wolfi base, distroless runner, OCI labels. + +== Deviations from the canonical template + +|=== +| Item | Canonical | Here | Why + +| Source dir | `src/` | `lib/` | Elixir convention +| Test dir | `tests/` | `test/` | Elixir convention +| State file | root `STATE.scm` | `.machine_readable/6a2/STATE.a2ml` +| Project keeps STATE inside the broader machine-readable bundle + (META, ECOSYSTEM, NEUROSYM, PLAYBOOK) for consistency +|=== + +These deviations are documented and remain semantically equivalent. + +== References + +* link:docs/research/rsr-template.adoc[docs/research/rsr-template.adoc] — canonical RSR template +* https://rhodium.sh[Rhodium Standard] — upstream RSR documentation diff --git a/SECURITY.md b/SECURITY.md index 6b44bac..6698f02 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -18,7 +18,7 @@ We take security seriously. If you discover a security vulnerability, please fol ### Reporting Process 1. **Do NOT** create a public GitHub issue for security vulnerabilities -2. Email security concerns to the maintainers (see MAINTAINERS.md) +2. Email security concerns to the maintainers (see MAINTAINERS.adoc) 3. Include: - Description of the vulnerability - Steps to reproduce diff --git a/TOPOLOGY.md b/TOPOLOGY.md index 7307afe..b21bde9 100644 --- a/TOPOLOGY.md +++ b/TOPOLOGY.md @@ -1,10 +1,10 @@ - + # eTMA Handler (tma-mark2) — Project Topology -## Status: alpha scaffold (~25–30%) +## Status: alpha scaffold (~30–35%) The previous version of this file claimed ~90% completion. That was wrong. This is now an honest dashboard. See [ROADMAP.adoc](ROADMAP.adoc) for the path to v1. @@ -58,9 +58,9 @@ ELIXIR CRYPTO SURFACE Crypto.encrypt/3 (top-level) ░░░░░░░░░░ 0% STUB — placeholder body DATA PLANE (BLOCKING for v1) - Repo (CubDB) ░░░░░░░░░░ 0% STUB — 21-line module, no functions - FHI parser/generator ░░░░░░░░░░ 0% STUB — parse/1 + generate/1 unimplemented - Bouncer (file watcher) █░░░░░░░░░ ~10% init/1 references undefined symbols + Repo (CubDB) ███████░░░ ~70% 280 LOC + 237 LOC of tests; encryption-at-rest still TODO + FHI parser/generator ░░░░░░░░░░ 0% STUB — parse/1 + generate/1 unimplemented (Phase 1.2, waiting on real .fhi fixtures) + Bouncer (file watcher) ██░░░░░░░░ ~20% init/1 fixed (loud-fail stub); pipeline unimplemented (Phase 1.3) Scanner / Container ░░░░░░░░░░ 0% STUB .docx generator ░░░░░░░░░░ 0% No module, no dependency selected @@ -74,7 +74,7 @@ WEB LAYER MarkingLive (cockpit) ████░░░░░░ ~40% UI works against mock data; not wired to Repo SettingsLive ████░░░░░░ ~40% Shell present, persistence stubbed RefineryLive, CourseLive.* █░░░░░░░░░ ~10% "Coming soon" placeholders - ApiController /health ███░░░░░░░ ~30% Calls Repo.get/1 which does not exist + ApiController /health ███████░░░ ~70% Real liveness check against Repo.cubdb/0 EXTERNAL / DEFERRED (not on v1 path) Scheduling.Calendar ████░░░░░░ ~40% 689 LOC, untested, deferred to post-v1 @@ -91,29 +91,30 @@ SECURITY / GOVERNANCE Audit log ░░░░░░░░░░ 0% Not implemented TESTING - ExUnit suite (4 files) ██░░░░░░░░ ~20% calculator + crypto real; bouncer tests regex literals only + ExUnit suite (5 files) ███░░░░░░░ ~30% calculator + crypto + Repo + bouncer surface real; no e2e/property/fuzz No e2e, no property, no fuzz ░░░░░░░░░░ 0% REPO INFRASTRUCTURE Justfile / guix.scm █████████░ ~90% Solid; not exercised in CI - CI workflows ██████░░░░ ~60% 14 workflows; most are governance, not value-adding + CI workflows █████░░░░░ ~50% 14 workflows; governance-heavy; elixir-ci/test and rescript-deno-ci/build fail pre-existing on every PR (no local toolchain to debug); governance / Language-package-anti-pattern also red — see docs/status/ci-state.md Containerfiles ██████░░░░ ~60% Exist; never demonstrated to run the app Burrito release █░░░░░░░░░ ~10% Configured; never actually built/run ───────────────────────────────────────────────────────────────────────────── -OVERALL (to v1 scope): ███░░░░░░░ ~25-30% Scaffold + partial crypto + working calculator +OVERALL (to v1 scope): ████░░░░░░ ~30-35% Scaffold + partial crypto + Repo + working calculator ``` ## v1 Critical Path (see ROADMAP.adoc) ``` -1. Repo (CubDB) ──┐ +1. Repo (CubDB) ✓ ┐ 2. FHI parser ────┼──► 3. Bouncer ──► 4. .docx gen ──► 5. MarkingLive wired ──► 6. Auth + at-rest ──► 7. Burrito release │ └── golden tests ``` -Nothing past step 1 can be honestly claimed complete until step 1 lands. +Step 1 landed in Phase 1.1 (commit 779885d on `main`). Step 2 is waiting +on real anonymised `.fhi` fixtures in `test/fixtures/fhi/`. ## Update Protocol diff --git a/assets/js/app.js b/assets/js/app.js index 064c7f3..2f3ffa9 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,27 +1,31 @@ // SPDX-License-Identifier: MPL-2.0 // Phoenix LiveView application entry point -import "phoenix_html" -import {Socket} from "phoenix" -import {LiveSocket} from "phoenix_live_view" -import topbar from "../vendor/topbar" +import "phoenix_html"; +import { Socket } from "phoenix"; +import { LiveSocket } from "phoenix_live_view"; +import topbar from "../vendor/topbar"; -let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") -let liveSocket = new LiveSocket("/live", Socket, { +const csrfToken = document.querySelector("meta[name='csrf-token']") + .getAttribute("content"); +const liveSocket = new LiveSocket("/live", Socket, { longPollFallbackMs: 2500, - params: {_csrf_token: csrfToken} -}) + params: { _csrf_token: csrfToken }, +}); // Show progress bar on live navigation and form submits -topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) -window.addEventListener("phx:page-loading-start", _info => topbar.show(300)) -window.addEventListener("phx:page-loading-stop", _info => topbar.hide()) +topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" }); +globalThis.addEventListener( + "phx:page-loading-start", + (_info) => topbar.show(300), +); +globalThis.addEventListener("phx:page-loading-stop", (_info) => topbar.hide()); // connect if there are any LiveViews on the page -liveSocket.connect() +liveSocket.connect(); // expose liveSocket on window for web console debug logs and latency simulation: // >> liveSocket.enableDebug() // >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session // >> liveSocket.disableLatencySim() -window.liveSocket = liveSocket +globalThis.liveSocket = liveSocket; diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..9dc64e8 --- /dev/null +++ b/deno.json @@ -0,0 +1,21 @@ +{ + "lint": { + "exclude": [ + "assets/vendor/", + "deps/", + "_build/", + "node_modules/" + ] + }, + "fmt": { + "include": [ + "assets/js/" + ], + "exclude": [ + "assets/vendor/", + "deps/", + "_build/", + "node_modules/" + ] + } +} diff --git a/docs/README.adoc b/docs/README.adoc new file mode 100644 index 0000000..8148dd6 --- /dev/null +++ b/docs/README.adoc @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: MPL-2.0 += tma-mark2 — Documentation Index +:toc: + +The documentation tree groups files by **intent**, not by file type. +Pick the entry point that matches what you need to do. + +== If you want to… + +[cols="1,3"] +|=== +| Goal | Start here + +| Run the app +| link:../QUICKSTART-USER.adoc[QUICKSTART-USER.adoc] at the repo root + +| Set up a development environment +| link:../QUICKSTART-DEV.adoc[QUICKSTART-DEV.adoc] + +| Cut a release or maintain the project +| link:../QUICKSTART-MAINTAINER.adoc[QUICKSTART-MAINTAINER.adoc] + +| See where the project is heading +| link:../ROADMAP.adoc[ROADMAP.adoc] + +| See where the project is *now* +| link:../TOPOLOGY.md[TOPOLOGY.md] — live completion dashboard + +| Brief a new AI agent before it touches the code +| link:../0-AI-MANIFEST.a2ml[0-AI-MANIFEST.a2ml] (canonical), + link:ai/warmup-dev.md[ai/warmup-dev.md] (dev focus), + link:ai/warmup-user.md[ai/warmup-user.md] (user focus) + +| Understand a design decision +| link:architecture/[architecture/] + +| Read the file-format spec for `.fhi` +| link:specs/fhi-schema.adoc[specs/fhi-schema.adoc] + +| Add or audit tests +| link:status/test-needs.md[status/test-needs.md] +|=== + +== Directory map + +[cols="1,3"] +|=== +| Path | What lives here + +| link:architecture/[architecture/] +| System design, governance frameworks (MAA, RMR, RMO), architectural + decision records. + +| link:ai/[ai/] +| Briefings for LLM agents working on the code. Pair with + link:../0-AI-MANIFEST.a2ml[0-AI-MANIFEST.a2ml] at the root. + +| link:examples/[examples/] +| Illustrative examples — sample forensics report, sample Nickel + config. Compare to `examples/` at the repo root, which holds + *runtime* example data. + +| link:operations/[operations/] +| Runbooks and operational concerns — failure modes, reversibility. + +| link:research/[research/] +| Background and rationale — Palimpsest licence philosophy, + competitor analysis, citations, brainstormed ideas. + +| link:sessions/[sessions/] +| STATE.scm conversation checkpoints from collaborative sessions. + +| link:specs/[specs/] +| Protocol and format specifications — `.fhi` schema, integrity + guarantees. + +| link:status/[status/] +| Live status reports — test coverage gaps, proof-obligation gaps, + internal code-review notes (SEAMS). + +| link:wiki/[wiki/] +| GitHub Wiki staging area. Markdown source for the pages at + https://github.com/hyperpolymath/tma-mark2/wiki — see + link:wiki/README.md[wiki/README.md] for the sync procedure. +|=== + +== Machine-readable artefacts + +Project state, ecosystem, and agent-interaction patterns are tracked +under link:../.machine_readable/[.machine_readable/]. See +link:../.claude/CLAUDE.md[.claude/CLAUDE.md] for the index. + +== Conventions + +* AsciiDoc (`.adoc`) for long-form documents that benefit from a + table of contents or structured cross-references. +* Markdown (`.md`) for shorter pieces and anything GitHub renders by + default. +* File names are kebab-case under `docs/`. The top-level community + files (README, CHANGELOG, CONTRIBUTING, …) keep their conventional + UPPER_CASE names. +* Every file carries an SPDX-License-Identifier header. diff --git a/llm-warmup-dev.md b/docs/ai/warmup-dev.md similarity index 100% rename from llm-warmup-dev.md rename to docs/ai/warmup-dev.md diff --git a/llm-warmup-user.md b/docs/ai/warmup-user.md similarity index 100% rename from llm-warmup-user.md rename to docs/ai/warmup-user.md diff --git a/docs/FORENSICS-REPORT-EXAMPLE.adoc b/docs/examples/forensics-report.adoc similarity index 100% rename from docs/FORENSICS-REPORT-EXAMPLE.adoc rename to docs/examples/forensics-report.adoc diff --git a/configs/config.ncl b/docs/examples/nickel-config-example.ncl similarity index 50% rename from configs/config.ncl rename to docs/examples/nickel-config-example.ncl index 5731962..f37da25 100644 --- a/configs/config.ncl +++ b/docs/examples/nickel-config-example.ncl @@ -1,4 +1,6 @@ -# Configuration generation +# SPDX-License-Identifier: MPL-2.0 +# Example: generic Nickel configuration. Not project config; included +# as a documentation reference for the Nickel language. { name = "my-app", replicas = diff --git a/docs/FAILURE-MODES.md b/docs/operations/failure-modes.md similarity index 100% rename from docs/FAILURE-MODES.md rename to docs/operations/failure-modes.md diff --git a/REVERSIBILITY.md b/docs/operations/reversibility.md similarity index 100% rename from REVERSIBILITY.md rename to docs/operations/reversibility.md diff --git a/docs/CITATIONS.adoc b/docs/research/citations.adoc similarity index 100% rename from docs/CITATIONS.adoc rename to docs/research/citations.adoc diff --git a/docs/COMPETITORS.md b/docs/research/competitors.md similarity index 100% rename from docs/COMPETITORS.md rename to docs/research/competitors.md diff --git a/docs/IDEAS.md b/docs/research/ideas.md similarity index 100% rename from docs/IDEAS.md rename to docs/research/ideas.md diff --git a/docs/research/palimpsest.adoc b/docs/research/palimpsest.adoc new file mode 100644 index 0000000..abcbb76 --- /dev/null +++ b/docs/research/palimpsest.adoc @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MPL-2.0 += Palimpsest License +:toc: +:toc-placement!: + +image:https://img.shields.io/badge/License-MPL--2.0-blue.svg[License: MPL-2.0,link="https://github.com/hyperpolymath/palimpsest-license"] +image:https://img.shields.io/badge/Philosophy-Palimpsest-indigo.svg[Palimpsest,link="https://github.com/hyperpolymath/palimpsest-license"] + +toc::[] + +== Legal Status + +This project is licensed under the **Palimpsest License (MPL-2.0)** — a +philosophical extension of the Mozilla Public License 2.0 maintained by +the hyperpolymath ecosystem. + +For SPDX detectors and licence-aware tooling, the canonical identifier +is `MPL-2.0`. See link:../../NOTICE[NOTICE] for the full disposition, +and link:../../LICENSE[LICENSE] for the binding legal text. + +NOTE: This document supersedes the earlier PMPL-1.0 / PMPL-1.0-or-later +identifiers used in the project's pre-migration history. SPDX headers +throughout the codebase now consistently use `MPL-2.0`. + +== What the Palimpsest extension adds + +* **Emotional Lineage** — preserve narrative intent and cultural context +* **Provenance Integrity** — retain attribution and lineage metadata +* **Ethical Use Constraints** — explicit consent for non-interpretive AI training +* **Quantum-Safe Provenance** (optional) — post-quantum signature support + +These obligations sit on top of, not in conflict with, the MPL-2.0 +copyleft provisions. + +== How to adopt in a new project + +1. Copy the MPL-2.0 text into `LICENSE` at the repository root. +2. Add a `NOTICE` file recording the Palimpsest extension. +3. Add SPDX headers to source files: ++ +[source] +---- +SPDX-License-Identifier: MPL-2.0 +SPDX-FileCopyrightText: +---- +4. Add a Palimpsest badge to your README (see the shield URL at the + top of this file). + +== References + +* link:../../LICENSE[LICENSE] — the binding MPL-2.0 text +* link:../../NOTICE[NOTICE] — Palimpsest disposition and tooling notes +* link:../../LICENSES/translations/[LICENSES/translations/] — Dutch + translations and source Palimpsest texts diff --git a/RSR_OUTLINE.adoc b/docs/research/rsr-template.adoc similarity index 100% rename from RSR_OUTLINE.adoc rename to docs/research/rsr-template.adoc diff --git a/docs/SESSION-2026-01-06.scm b/docs/sessions/2026-01-06.scm similarity index 100% rename from docs/SESSION-2026-01-06.scm rename to docs/sessions/2026-01-06.scm diff --git a/docs/FHI-SCHEMA.adoc b/docs/specs/fhi-schema.adoc similarity index 100% rename from docs/FHI-SCHEMA.adoc rename to docs/specs/fhi-schema.adoc diff --git a/docs/INTEGRITY.adoc b/docs/specs/integrity.adoc similarity index 99% rename from docs/INTEGRITY.adoc rename to docs/specs/integrity.adoc index 21b75aa..0dd303e 100644 --- a/docs/INTEGRITY.adoc +++ b/docs/specs/integrity.adoc @@ -479,8 +479,8 @@ The toolkit makes XML escaping errors impossible at compile time. == Related Documentation -* link:FHI-SCHEMA.adoc[FHI Schema Specification] -* link:architecture/overview.adoc[Architecture Overview] +* link:fhi-schema.adoc[FHI Schema Specification] +* link:../architecture/overview.adoc[Architecture Overview] * link:architecture/decisions.adoc[Architecture Decision Records] == Appendix: The 7/44 Test Cases diff --git a/docs/status/ci-state.md b/docs/status/ci-state.md new file mode 100644 index 0000000..c216080 --- /dev/null +++ b/docs/status/ci-state.md @@ -0,0 +1,96 @@ + + +# CI state on PR #41 (`claude/post-phase-1-1-cleanup`) + +PR: +Head SHA: `5b6a3c4`-ish (whatever is at HEAD when this file is read) +Captured: 2026-05-26 + +This file is a snapshot of the CI investigation done at the end of the +post-Phase-1.1 cleanup session, so that the open red checks have +context next time someone (human or agent) opens the PR. + +## Check status + +| Check | Conclusion | Disposition | +|-------|------------|-------------| +| CodeQL | ✓ success | | +| Hypatia | ✓ success | | +| governance / Security policy checks | ✓ success | | +| governance / Guix primary / Nix fallback policy | ✓ success | | +| governance / Code quality + docs | ✓ success | | +| governance / Well-Known (RFC 9116 + RSR) | ✓ success | | +| governance / Workflow security linter | ✓ success | | +| governance / Language / package anti-pattern policy | ✗ failure | Pre-existing — reusable workflow lives in `hyperpolymath/standards` and is out of scope for this PR. | +| trufflehog | ✓ success | | +| gitleaks | ✓ success | | +| rust-secrets | ✓ success | | +| analyze (CodeQL js-ts) | ✓ success | | +| Hypatia Neurosymbolic Analysis | ✓ success | | +| `test` (×2, elixir-ci + duplicate) | ✗ failure | Fails in 1–2 s — likely setup/compile step. Cannot reproduce locally: no Elixir toolchain in the remote-execution container. | +| `build` (×2, rescript-deno-ci + duplicate) | ✗ failure | Fails in 7–8 s — likely `deno fmt --check` on the new markdown files under `docs/wiki/`. No `deno.json` ignore section to bypass. | +| `check` (×2) | ✓ success | | +| `security` (×2) | ✓ success | | + +The `(×2)` jobs run twice because `elixir-ci.yml` and +`rescript-deno-ci.yml` both use `on: [push, pull_request]`, so each +SHA triggers both event types. + +## Bot findings + +The Hypatia bot reported 98 findings on the PR. The breakdown: + +* **3 critical** — all pre-existing in `main`: + * `Code.eval_*` use in `lib/etma_handler/logic/calculator.ex` + * "Secret found" pattern in `lib/etma_handler/crypto/encrypted_storage.ex:36` + * "Secret found" pattern in `lib/etma_handler/crypto/suite.ex:266` +* **58 high** — mostly `expect()` in Rust hot paths (`native/tma_crypto/src/lib.rs`), + `binary_to_term` without `:safe`, and the `setup.sh` curl-pipe pattern. + All pre-existing in `main`. +* **37 medium** — one was actionable in this PR: + * `docs/examples/nickel-config-example.ncl` missing SPDX header — + introduced by moving the file out of `configs/`. **Fixed in this PR.** + * The rest are pre-existing (CodeQL language-matrix issue, etc.). + +## What's safe vs unsafe to assume + +**Safe** to assume done from this PR: + +* Repo tidy is complete — see `CHANGELOG.adoc [Unreleased]` for the + full list. Eight commits, 95+ files touched. +* `docs/wiki/` is staged for the GitHub wiki — see + `docs/wiki/README.md` for the sync recipe. +* SPDX-License-Identifier coverage is now complete on every file in + the repository (the Nickel example was the last gap). +* Bouncer compiles cleanly with a loud-fail stub (was previously a + non-compiling stub). +* PMPL → MPL-2.0 migration is finished (was incomplete on `main`). + +**Unsafe** to assume: + +* That CI is green. It isn't, and most of the red is pre-existing. + The PR is mergeable from a content-correctness standpoint but + not from a status-check standpoint. +* That `deno fmt` on the new markdown files would pass. It may + reformat headings/lists; can't verify without Deno locally. +* That `mix compile --warnings-as-errors` passes on this branch. + Likely fine (no functional Elixir changes in this PR beyond the + Bouncer stub), but unverified — the `test` job fails too fast for + the failure to be in test runs themselves. + +## What's needed to take CI to green + +Out of scope for this PR but documented for the next pass: + +1. Find why `elixir-ci / test` fails inside the first ~2 s on every + PR. Suspect: cache action against a stale `mix.lock` key, or the + `erlef/setup-beam` Elixir/OTP combo (1.15/26) drifting from the + project pin (1.18.4/25 in `.tool-versions`). +2. Either add `docs/wiki/` to a Deno fmt ignore list or stop running + `rescript-deno-ci` on a repo that has no ReScript or Deno code. + The latter looks correct — this workflow appears templated in, + not used. +3. Open an issue against `hyperpolymath/standards` to see why + `governance / Language / package anti-pattern policy` flags this + repo. The reusable workflow's source is not visible from this + repository. diff --git a/PROOF-NEEDS.md b/docs/status/proof-needs.md similarity index 100% rename from PROOF-NEEDS.md rename to docs/status/proof-needs.md diff --git a/SEAMS_REVIEW.adoc b/docs/status/seams-review.adoc similarity index 100% rename from SEAMS_REVIEW.adoc rename to docs/status/seams-review.adoc diff --git a/TEST-NEEDS.md b/docs/status/test-needs.md similarity index 98% rename from TEST-NEEDS.md rename to docs/status/test-needs.md index 5f561f1..59841e9 100644 --- a/TEST-NEEDS.md +++ b/docs/status/test-needs.md @@ -13,7 +13,7 @@ The previous version of this file claimed "CRG Grade C ACHIEVED 2026-04-04". Tha | `test/etma_handler/bouncer_test.exs` | Regex literal pattern matching only — does **not** exercise the GenServer (which is broken) | Cosmetic | | `test/etma_handler/nlp_test.exs` | NLP NIF wrappers | Partial | -`tests/fuzz/` exists but has no payload yet. +`test/fuzz/` exists but has no payload yet. ## Rust NIF Tests diff --git a/docs/wiki/AI-Agent-Briefing.md b/docs/wiki/AI-Agent-Briefing.md new file mode 100644 index 0000000..4425726 --- /dev/null +++ b/docs/wiki/AI-Agent-Briefing.md @@ -0,0 +1,39 @@ +# AI Agent Briefing + +This project is designed for human + AI collaboration. The following files exist specifically to brief LLM agents before they touch the code. + +## Canonical entry points + +| File | When to read | Notes | +|------|--------------|-------| +| [`0-AI-MANIFEST.a2ml`](https://github.com/hyperpolymath/tma-mark2/blob/main/0-AI-MANIFEST.a2ml) | Always, first | Canonical locations, critical invariants, context tiers. | +| [`.claude/CLAUDE.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/.claude/CLAUDE.md) | Always | Language policy, banned tools, prohibited dependencies. | +| [`docs/ai/warmup-dev.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/ai/warmup-dev.md) | If you're modifying code | Developer-oriented briefing. | +| [`docs/ai/warmup-user.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/ai/warmup-user.md) | If you're helping an end user | User-oriented briefing. | +| [`TOPOLOGY.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/TOPOLOGY.md) | Before claiming a component works | Live completion dashboard. | + +## Machine-readable manifests + +The [`.machine_readable/`](https://github.com/hyperpolymath/tma-mark2/tree/main/.machine_readable) tree holds structured manifests that agents can parse without LLM inference: + +* [`.machine_readable/6a2/STATE.a2ml`](https://github.com/hyperpolymath/tma-mark2/blob/main/.machine_readable/6a2/STATE.a2ml) — current state & v1 critical-path step status. +* [`.machine_readable/6a2/META.a2ml`](https://github.com/hyperpolymath/tma-mark2/blob/main/.machine_readable/6a2/META.a2ml) — architecture decisions and development practices. +* [`.machine_readable/6a2/ECOSYSTEM.a2ml`](https://github.com/hyperpolymath/tma-mark2/blob/main/.machine_readable/6a2/ECOSYSTEM.a2ml) — ecosystem position. +* [`.machine_readable/6a2/AGENTIC.a2ml`](https://github.com/hyperpolymath/tma-mark2/blob/main/.machine_readable/6a2/AGENTIC.a2ml) — AI agent interaction patterns. +* [`.machine_readable/6a2/PLAYBOOK.a2ml`](https://github.com/hyperpolymath/tma-mark2/blob/main/.machine_readable/6a2/PLAYBOOK.a2ml) — operational runbook. + +## House rules for agents + +1. **Do not raise completion percentages** in `TOPOLOGY.md` above what is demonstrable. Docstrings and stub bodies are not progress. +2. **Do not introduce a banned language**. If you reach for TypeScript, Node, npm, Python, Go, Kotlin, or Swift, stop and ask. +3. **SPDX header on every new file**: `SPDX-License-Identifier: MPL-2.0`. +4. **CHANGELOG.adoc** gets an `[Unreleased]` entry for anything user-visible. +5. **One conceptual change per commit**. Commits should be reviewable in isolation. +6. Tests come with the code, not as a follow-up commit. + +## Boundary cases worth flagging early + +* Any change to encryption-at-rest, the FHI parser, or the supervision tree → ask before implementing. +* Anything that adds a new top-level directory → ask. +* Anything that removes or relocates files in `LICENSES/`, `.well-known/`, or `.machine_readable/6a2/` → ask. +* Anything that calls out to a third-party hosted service → ask. diff --git a/docs/wiki/Architecture.md b/docs/wiki/Architecture.md new file mode 100644 index 0000000..7382fdd --- /dev/null +++ b/docs/wiki/Architecture.md @@ -0,0 +1,52 @@ +# Architecture + +The architecture documents live in [`docs/architecture/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/architecture). This page is a navigational map. + +## System-level + +* [`docs/architecture/overview.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/overview.adoc) — high-level overview. +* [`docs/architecture/decisions.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/decisions.adoc) — architectural decision records. +* [`TOPOLOGY.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/TOPOLOGY.md) — current component completion dashboard. + +## Governance frameworks + +Three governance frameworks track different accountability dimensions: + +* [`docs/architecture/maa.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/maa.adoc) — **MAA** (Mission, Authority, Accountability) +* [`docs/architecture/rmr.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/rmr.adoc) — **RMR** (Risk, Mitigation, Recovery) +* [`docs/architecture/rmo.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/rmo.adoc) — **RMO** (Roles, Mandates, Operations) + +## Top-level shape + +``` + ┌──────────────────────────────────┐ + │ Tutor (browser, LiveView UI) │ + └────────────────┬─────────────────┘ + │ HTTP / WebSocket + ▼ + ┌──────────────────────────────────┐ + │ EtmaHandler (Elixir / OTP) │ + │ - Application supervision tree │ + │ - Phoenix endpoint │ + └────┬─────────────────────────────┘ + │ + ┌───────────────┼────────────────────────────┐ + ▼ ▼ ▼ + ┌──────────┐ ┌──────────────┐ ┌─────────────────┐ + │ Bouncer │ │ Repo │ │ Native (Rust) │ + │ watcher │ │ (CubDB) │ │ tma_crypto │ + └────┬─────┘ └──────┬───────┘ │ tma_nlp │ + │ │ └─────────────────┘ + ▼ ▼ + ┌─────────────────────────────┐ + │ Filesystem │ + │ ~/Downloads · vault · .docx │ + └─────────────────────────────┘ +``` + +The Bouncer pipeline (DETECT → SCAN → QUARANTINE → PACKAGE) is the planned ingestion flow; only the constant set is implemented today. + +## Specs that pin the architecture + +* [`docs/specs/fhi-schema.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/specs/fhi-schema.adoc) — `.fhi` file format. +* [`docs/specs/integrity.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/specs/integrity.adoc) — submission integrity guarantees (hash chains, signatures). diff --git a/docs/wiki/Development.md b/docs/wiki/Development.md new file mode 100644 index 0000000..bc6c769 --- /dev/null +++ b/docs/wiki/Development.md @@ -0,0 +1,62 @@ +# Development + +## Read first + +* [`CONTRIBUTING.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/CONTRIBUTING.md) — contribution workflow, perimeter rules, what gets reviewed. +* [`CODE_OF_CONDUCT.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/CODE_OF_CONDUCT.adoc) — Contributor Covenant. +* [`.claude/CLAUDE.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/.claude/CLAUDE.md) — language policy (which languages are allowed and which are banned). + +## Language policy in one paragraph + +Elixir is the application language. Rust is for the NIFs in `native/`. ReScript will be the frontend language (planned, not yet wired). Nickel holds structural contracts under `must/`. Bash is allowed for scripts. **TypeScript, Node, npm, Python, Go, Kotlin, Swift, Flutter are banned.** Mobile, if ever revived, goes through Tauri 2.0 or Dioxus. + +## Repository layout (top level) + +``` +tma-mark2/ +├── lib/ # Elixir source +├── test/ # ExUnit tests (incl. test/fuzz/) +├── native/ # Rust NIFs +├── config/ # Elixir build/runtime configuration +├── must/ # Nickel structural contracts +├── docs/ # All long-form documentation +│ ├── architecture/ ai/ examples/ operations/ +│ ├── research/ sessions/ specs/ status/ +├── experiments/ # Post-v1 sketches (mobile, AffineScript, …) +├── .machine_readable/ # Project state, ecosystem manifests, agent instructions +├── .well-known/ # RFC metadata (security.txt, ai.txt, humans.txt) +├── Justfile # Task runner +├── guix.scm # Guix manifest +├── mix.exs # Elixir project definition +└── Containerfile{,.hardened} +``` + +## Daily loops + +```bash +just dev # phx.server +just test # ExUnit +just test path/to/file.exs # targeted +just quality # format + lint + test +just ci # full CI pipeline locally +``` + +## Status reports to update + +When you change a surface, also bump: + +* [`TOPOLOGY.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/TOPOLOGY.md) — completion dashboard. +* [`CHANGELOG.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/CHANGELOG.adoc) — under `[Unreleased]`. +* The relevant file under [`docs/status/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/status) if you fix a known gap. + +## Testing philosophy + +ExUnit is the primary harness. Property tests, fuzz tests, and golden tests are tracked in [`docs/status/test-needs.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/status/test-needs.md) — many slots are not yet filled. New code that talks to the data plane should ship with at least: + +1. Happy path unit test +2. One adversarial input +3. Round-trip if the code serialises + +## SPDX headers + +Every source file carries `SPDX-License-Identifier: MPL-2.0`. CI enforces this. diff --git a/docs/wiki/Documentation-Index.md b/docs/wiki/Documentation-Index.md new file mode 100644 index 0000000..62201a0 --- /dev/null +++ b/docs/wiki/Documentation-Index.md @@ -0,0 +1,33 @@ +# Documentation Index + +This page mirrors [`docs/README.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/README.adoc) — refer to that file in the repository for the authoritative version. + +## By directory + +| Path | What's inside | +|------|---------------| +| [`docs/architecture/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/architecture) | System design, governance frameworks (MAA, RMR, RMO), ADRs. | +| [`docs/ai/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/ai) | LLM agent briefings. | +| [`docs/examples/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/examples) | Illustrative examples — forensics report, Nickel config. | +| [`docs/operations/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/operations) | Runbooks — failure modes, reversibility. | +| [`docs/research/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/research) | Background — Palimpsest licence, competitors, citations, ideas. | +| [`docs/sessions/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/sessions) | STATE.scm conversation checkpoints. | +| [`docs/specs/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/specs) | FHI schema and integrity specifications. | +| [`docs/status/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/status) | Live status reports — test-needs, proof-needs, SEAMS review. | + +## Top-level companion documents + +| File | Purpose | +|------|---------| +| [`README.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/README.adoc) | Project overview. | +| [`ROADMAP.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/ROADMAP.adoc) | v1 plan. | +| [`TOPOLOGY.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/TOPOLOGY.md) | Live completion dashboard. | +| [`EXPLAINME.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/EXPLAINME.adoc) | README claims, backed by receipts. | +| [`CHANGELOG.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/CHANGELOG.adoc) | Release history. | +| [`CONTRIBUTING.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/CONTRIBUTING.md) | Contribution workflow. | +| [`GOVERNANCE.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/GOVERNANCE.adoc) | Decision-making model. | +| [`MAINTAINERS.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/MAINTAINERS.adoc) | Current maintainers. | +| [`SECURITY.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/SECURITY.md) | Reporting a vulnerability. | +| [`RSR_COMPLIANCE.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/RSR_COMPLIANCE.adoc) | RSR compliance state. | +| [`CLAUDE.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/CLAUDE.adoc) | AI-context entry document. | +| [`0-AI-MANIFEST.a2ml`](https://github.com/hyperpolymath/tma-mark2/blob/main/0-AI-MANIFEST.a2ml) | Canonical AI manifest. | diff --git a/docs/wiki/FHI-Format.md b/docs/wiki/FHI-Format.md new file mode 100644 index 0000000..7495dd7 --- /dev/null +++ b/docs/wiki/FHI-Format.md @@ -0,0 +1,22 @@ +# FHI Format + +The authoritative specification is [`docs/specs/fhi-schema.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/specs/fhi-schema.adoc). Companion: [`docs/specs/integrity.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/specs/integrity.adoc) for the integrity guarantees (hash chains, signatures). + +## In one sentence + +A `.fhi` file is the wire format the Open University's submission system uses to ship a student's electronic Tutor-Marked Assignment to a tutor for marking. The eTMA Handler consumes `.fhi` on the inbound side and emits a graded `.docx` on the outbound side. + +## Status of the parser + +| Surface | Status | +|---------|--------| +| Parser (`.fhi` → struct) | 0% — stub | +| Generator (struct → `.fhi`) | 0% — stub | +| Test fixtures (`test/fixtures/fhi/`) | empty — Phase 1.2 is blocked here | + +The parser is the next milestone on the [v1 critical path](Roadmap-and-Status); progress is gated on obtaining ≥ 5 real anonymised `.fhi` samples. + +## See also + +* [`EXPLAINME.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/EXPLAINME.adoc) for the README claims this format backs up. +* [`docs/architecture/overview.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/overview.adoc) for where the parser sits in the pipeline. diff --git a/docs/wiki/Getting-Started.md b/docs/wiki/Getting-Started.md new file mode 100644 index 0000000..f6bcf4f --- /dev/null +++ b/docs/wiki/Getting-Started.md @@ -0,0 +1,48 @@ +# Getting Started + +> The application is in early-stage scaffold. The end-to-end marking flow is not yet wired up — see [Roadmap and Status](Roadmap-and-Status). What follows lets you compile, run the test suite, and bring up the Phoenix shell. + +## Audiences + +| You are a… | Start with | +|------------|------------| +| End user (tutor) | [`QUICKSTART-USER.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/QUICKSTART-USER.adoc) | +| Developer | [`QUICKSTART-DEV.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/QUICKSTART-DEV.adoc) | +| Maintainer cutting a release | [`QUICKSTART-MAINTAINER.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/QUICKSTART-MAINTAINER.adoc) | + +## Prerequisites + +* Elixir 1.18+ with OTP 25 (pinned in `.tool-versions`) +* Rust + Cargo (for the native NIFs in `native/`) +* Node.js 18+ (for Phoenix assets) +* Optionally: GNU Guix for reproducible builds (`guix.scm`) + +The simplest install uses [asdf](https://asdf-vm.com/): + +```bash +asdf install +mix deps.get +mix assets.setup +mix assets.build +mix phx.server +``` + +Then open . + +## Just recipes + +The project uses [`just`](https://github.com/casey/just) as a thin task runner over `mix`. Common recipes: + +```bash +just dev # development server +just test # full ExUnit suite +just build # Guix → Mix cascade +just info # project info +just # list all recipes (about 70) +``` + +## What to expect + +The Phoenix endpoint comes up and serves a shell UI. The data plane (FHI parser, file watcher, .docx generator) is not wired through yet — you can compile, test, and load LiveView pages, but you cannot mark a real assignment end-to-end. + +For a component-by-component status, see [Roadmap and Status](Roadmap-and-Status). diff --git a/docs/wiki/Governance.md b/docs/wiki/Governance.md new file mode 100644 index 0000000..5520643 --- /dev/null +++ b/docs/wiki/Governance.md @@ -0,0 +1,23 @@ +# Governance + +Authoritative documents in the repository: + +* [`GOVERNANCE.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/GOVERNANCE.adoc) — decision-making model. +* [`MAINTAINERS.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/MAINTAINERS.adoc) — current maintainers. +* [`CODE_OF_CONDUCT.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/CODE_OF_CONDUCT.adoc) — Contributor Covenant. + +## Frameworks + +Three governance frameworks track different accountability dimensions: + +* [`docs/architecture/maa.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/maa.adoc) — Mission, Authority, Accountability. +* [`docs/architecture/rmr.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/rmr.adoc) — Risk, Mitigation, Recovery. +* [`docs/architecture/rmo.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/rmo.adoc) — Roles, Mandates, Operations. + +## Decisions + +Architectural decisions are recorded in [`docs/architecture/decisions.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/architecture/decisions.adoc). + +## Security + +Vulnerability reports go through [`SECURITY.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/SECURITY.md). The `.well-known/security.txt` file lists the contact channel. diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md new file mode 100644 index 0000000..375ca46 --- /dev/null +++ b/docs/wiki/Home.md @@ -0,0 +1,41 @@ +# tma-mark2 — eTMA Handler + +The BEAM edition of the Open University's electronic Tutor-Marked Assignment (eTMA) marking tool. Elixir / Phoenix on the backend, Rust NIFs for cryptography and NLP, a Phoenix LiveView UI on the way. + +> ⚠️ **Status: alpha scaffold (~30–35%)** — see [Roadmap and Status](Roadmap-and-Status) for an honest dashboard. This is not a runnable product yet. + +## Quick links + +| Goal | Page | +|------|------| +| Install / run the app | [Getting Started](Getting-Started) | +| See where the project stands | [Roadmap and Status](Roadmap-and-Status) | +| Understand the architecture | [Architecture](Architecture) | +| Contribute code | [Development](Development) | +| Brief an AI agent | [AI Agent Briefing](AI-Agent-Briefing) | +| Audit compliance | [RSR Compliance](RSR-Compliance) | +| Read the file-format spec | [FHI Format](FHI-Format) | +| Find a document by intent | [Documentation Index](Documentation-Index) | + +## What is the eTMA Handler? + +When complete, the application will: + +1. Watch the user's Downloads folder for `.fhi` student submissions. +2. Verify, decompress, and store them in a local CubDB vault. +3. Present a Phoenix LiveView marking cockpit for tutors. +4. Generate graded `.docx` files for return to students. +5. Run entirely offline; ship as a single Burrito binary. + +The original Java implementation predates this repo; this is a clean re-architecture rather than a port. + +## Repository + +* Source: +* License: Palimpsest License (MPL-2.0) — see [License](License) +* Governance: see [Governance](Governance) +* Author: Jonathan D.A. Jewell ([@hyperpolymath](https://github.com/hyperpolymath)) + +## How this wiki relates to the repository + +This wiki is a **navigation layer**, not a source of truth. Every authoritative document lives in the repository under `docs/` and is linked from here. If a wiki page disagrees with the repository, the repository wins. diff --git a/docs/wiki/License.md b/docs/wiki/License.md new file mode 100644 index 0000000..22f6d7b --- /dev/null +++ b/docs/wiki/License.md @@ -0,0 +1,28 @@ +# License + +This project is licensed under the **Palimpsest License (MPL-2.0)** — a philosophical extension of the Mozilla Public License 2.0 maintained by the hyperpolymath ecosystem. + +* **SPDX identifier**: `MPL-2.0` +* **Binding text**: [`LICENSE`](https://github.com/hyperpolymath/tma-mark2/blob/main/LICENSE) (standard MPL-2.0) +* **Palimpsest text**: [`LICENSES/MPL-2.0.txt`](https://github.com/hyperpolymath/tma-mark2/blob/main/LICENSES/MPL-2.0.txt) +* **Disposition**: [`NOTICE`](https://github.com/hyperpolymath/tma-mark2/blob/main/NOTICE) +* **Philosophy**: [`docs/research/palimpsest.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/research/palimpsest.adoc) + +## What the Palimpsest extension adds + +* Emotional Lineage — preserve narrative intent and cultural context. +* Provenance Integrity — retain attribution and lineage metadata. +* Ethical Use Constraints — explicit consent for non-interpretive AI training. +* Quantum-Safe Provenance (optional) — post-quantum signature support. + +These obligations sit on top of, not in conflict with, MPL-2.0 copyleft. + +## Translations + +* [`LICENSES/translations/MPL-2.0-NL.txt`](https://github.com/hyperpolymath/tma-mark2/blob/main/LICENSES/translations/MPL-2.0-NL.txt) — Dutch. +* [`LICENSES/translations/PALIMPSEST-EN.txt`](https://github.com/hyperpolymath/tma-mark2/blob/main/LICENSES/translations/PALIMPSEST-EN.txt) +* [`LICENSES/translations/PALIMPSEST-NL.txt`](https://github.com/hyperpolymath/tma-mark2/blob/main/LICENSES/translations/PALIMPSEST-NL.txt) + +## Historical note + +The project carried `PMPL-1.0` / `PMPL-1.0-or-later` SPDX identifiers prior to the May 2026 migration. All headers now read `MPL-2.0`; the older identifiers are retained only as historical references in [`CHANGELOG.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/CHANGELOG.adoc). diff --git a/docs/wiki/README.md b/docs/wiki/README.md new file mode 100644 index 0000000..67286bc --- /dev/null +++ b/docs/wiki/README.md @@ -0,0 +1,64 @@ + + +# docs/wiki/ — GitHub Wiki staging area + +This directory holds the **source of truth** for the + pages. Files here are +plain Markdown using the conventions GitHub wikis expect: + +| File | Role | +|------|------| +| `Home.md` | Wiki landing page (required by GitHub wikis). | +| `_Sidebar.md` | Sidebar — appears on every page. | +| `_Footer.md` | Footer — appears on every page. | +| `.md` | A wiki page. The filename (sans `.md`) is the URL slug. | + +## Why the staging area exists + +GitHub wikis live in a separate Git repository +(`tma-mark2.wiki.git`) outside this repo's CI / signing scope. The +files are versioned here so: + +* The wiki copy is reviewable through pull requests on the main repo. +* The wiki cannot drift silently — the canonical content is in this + tree and tracked alongside the rest of the codebase. +* If the GitHub wiki is wiped or corrupted, restoring it is just a + copy operation. + +## Editing rules + +1. Treat these pages as a **navigation layer** only. Authoritative + content lives elsewhere in `docs/`, `README.adoc`, `TOPOLOGY.md`, + etc. Wiki pages link to those — they do not duplicate the content. +2. If a wiki page disagrees with the repository, fix the wiki page, + not the repository. +3. Every link should point to a stable file on `main` using the form + `https://github.com/hyperpolymath/tma-mark2/blob/main/`. + +## Deploying the staged content to the wiki + +The wiki repo lives at `https://github.com/hyperpolymath/tma-mark2.wiki.git`. +To push these files there: + +```bash +# One-time clone of the wiki repo (next to this repo) +git clone https://github.com/hyperpolymath/tma-mark2.wiki.git ../tma-mark2.wiki + +# Sync the staged files +cp docs/wiki/*.md ../tma-mark2.wiki/ + +# Commit and push +cd ../tma-mark2.wiki +git add -A +git commit -m "Sync wiki from docs/wiki/" +git push origin master +``` + +### Optional: automate via GitHub Actions + +If you'd like the wiki to update automatically on every push to `main` +that touches `docs/wiki/**`, add a workflow that uses the +[`Andrew-Chen-Wang/github-wiki-action`](https://github.com/Andrew-Chen-Wang/github-wiki-action) +or similar published action. We don't ship that workflow by default +because it requires write permission on the wiki repo and the +project's signing/CI policy hasn't yet been extended to cover it. diff --git a/docs/wiki/RSR-Compliance.md b/docs/wiki/RSR-Compliance.md new file mode 100644 index 0000000..0b93d83 --- /dev/null +++ b/docs/wiki/RSR-Compliance.md @@ -0,0 +1,27 @@ +# RSR Compliance + +The authoritative compliance state lives in [`RSR_COMPLIANCE.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/RSR_COMPLIANCE.adoc) at the repo root. This wiki page is a summary. + +## Summary + +| Tier | Status | +|------|--------| +| RSR required files | ✓ pass | +| Language policy | ✓ pass (Elixir tier 1; ReScript planned) | +| Build system | ✓ pass (Guix primary, Mix fallback) | +| Container | ✓ pass (`Containerfile` + `Containerfile.hardened`) | +| `.well-known/` metadata | ✓ pass | +| License + SPDX | ✓ pass (MPL-2.0 across the tree) | +| Documentation taxonomy | ✓ pass (`docs/{architecture,specs,…}`) | +| State tracking | partial — uses `.machine_readable/6a2/STATE.a2ml` rather than a root-level `STATE.scm` | + +## Intentional deviations from the canonical RSR template + +* Source dir is `lib/`, not `src/` — Elixir convention. +* Test dir is `test/`, not `tests/` — Elixir convention. +* State lives at `.machine_readable/6a2/STATE.a2ml` rather than a root `STATE.scm`. This keeps STATE next to its peers (META, ECOSYSTEM, NEUROSYM, PLAYBOOK, AGENTIC). + +## Reference + +* Template definition: [`docs/research/rsr-template.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/docs/research/rsr-template.adoc) +* Upstream standard: diff --git a/docs/wiki/Roadmap-and-Status.md b/docs/wiki/Roadmap-and-Status.md new file mode 100644 index 0000000..6180749 --- /dev/null +++ b/docs/wiki/Roadmap-and-Status.md @@ -0,0 +1,56 @@ +# Roadmap and Status + +The single source of truth for project state is the repository: + +* [`TOPOLOGY.md`](https://github.com/hyperpolymath/tma-mark2/blob/main/TOPOLOGY.md) — live component-by-component completion dashboard. +* [`ROADMAP.adoc`](https://github.com/hyperpolymath/tma-mark2/blob/main/ROADMAP.adoc) — the v1 critical path and milestones. +* [`docs/status/`](https://github.com/hyperpolymath/tma-mark2/tree/main/docs/status) — test-needs, proof-needs, SEAMS review. + +This wiki page is a navigational summary. If it disagrees with `TOPOLOGY.md`, trust the repository. + +## Overall status + +**Alpha scaffold (~30–35% of v1 scope).** A Phoenix shell, the Rust crypto/NLP NIFs, the CubDB Repo, and the marking calculator are real. The rest of the data plane and most of the UI are unimplemented or mock-wired. + +## v1 critical path + +``` +1. Repo (CubDB) ✓ Phase 1.1 — landed on main +2. FHI parser ░ Phase 1.2 — blocked on real .fhi fixtures +3. Bouncer file watcher ░ Phase 1.3 — stub only +4. .docx generator ░ No dep selected +5. MarkingLive wired ░ Currently on mock data +6. Auth + at-rest crypt ░ WebAuthn module exists, not wired +7. Burrito release ░ Configured but never demonstrated +``` + +Nothing past step 1 can be honestly claimed complete until step 1 lands on `main` (it has). Step 2 needs ≥ 5 anonymised `.fhi` samples in `test/fixtures/fhi/`. + +## What's solid + +| Surface | Status | Notes | +|---------|--------|-------| +| Rust NIFs (`tma_crypto`, `tma_nlp`) | ~90% | 1051 LOC, wired through Rustler | +| `Crypto.Hybrid` (KEM) | ~80% | Needs integration tests | +| `Logic.Calculator` | ~90% | Real ExUnit tests, used by UI | +| `Repo` (CubDB) | ~70% | 280 LOC + 237 LOC tests; encryption-at-rest still TODO | +| Phoenix scaffold | ~80% | Router, endpoint, components | +| Repo infra (`Justfile`, `guix.scm`) | ~90% | Solid; not exercised in CI | + +## What's a stub + +| Surface | Status | Notes | +|---------|--------|-------| +| FHI parser / generator | 0% | Phase 1.2 | +| Bouncer ingestion pipeline | 20% | `init/1` compiles cleanly with a loud-fail stub; pipeline unimplemented | +| Scanner / Container | 0% | | +| `.docx` generator | 0% | No dependency selected | +| 15 `Marking.*` modules | 0% | All docstring stubs | +| AuthN / AuthZ | 0% | No login pipeline | +| Encryption at rest | 0% | Repo writes plaintext | +| DPIA / threat model | 0% | `SECURITY.md` is generic boilerplate | +| Audit log | 0% | | + +## Deferred (post-v1) + +`Scheduling.Calendar`, `External.Zotero`, `Proven.SafeStateMachine`, mobile (Tauri/Dioxus skeleton), AffineScript frontend, Bebop/Zig FFI. See [`experiments/`](https://github.com/hyperpolymath/tma-mark2/tree/main/experiments). diff --git a/docs/wiki/_Footer.md b/docs/wiki/_Footer.md new file mode 100644 index 0000000..9aefcd8 --- /dev/null +++ b/docs/wiki/_Footer.md @@ -0,0 +1 @@ +[hyperpolymath/tma-mark2](https://github.com/hyperpolymath/tma-mark2) · Palimpsest License (MPL-2.0) · status: alpha scaffold · This wiki mirrors the canonical docs in the repository. diff --git a/docs/wiki/_Sidebar.md b/docs/wiki/_Sidebar.md new file mode 100644 index 0000000..17bca10 --- /dev/null +++ b/docs/wiki/_Sidebar.md @@ -0,0 +1,22 @@ +## tma-mark2 + +* **[Home](Home)** +* [Getting Started](Getting-Started) +* [Roadmap and Status](Roadmap-and-Status) + +### Reference + +* [Architecture](Architecture) +* [FHI Format](FHI-Format) +* [Documentation Index](Documentation-Index) + +### Contribute + +* [Development](Development) +* [AI Agent Briefing](AI-Agent-Briefing) +* [Governance](Governance) + +### Project meta + +* [RSR Compliance](RSR-Compliance) +* [License](License) diff --git a/build-affine.sh b/experiments/affine-frontend/build.sh similarity index 70% rename from build-affine.sh rename to experiments/affine-frontend/build.sh index 882c75b..ba0e7bf 100755 --- a/build-affine.sh +++ b/experiments/affine-frontend/build.sh @@ -3,8 +3,11 @@ # SPDX-License-Identifier: MPL-2.0 set -euo pipefail -ROOT_DIR="$(cd "$(dirname "$0")" && pwd)" -OUT_DIR="$ROOT_DIR/priv/static/wasm" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +# Script lives at experiments/affine-frontend/build.sh — walk up two levels +# to reach the project root. +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +OUT_DIR="$PROJECT_ROOT/priv/static/wasm" OUT_WASM="$OUT_DIR/etma_handler_frontend.wasm" TMP_WASM="$OUT_DIR/.etma_handler_frontend.wasm.tmp" @@ -14,8 +17,8 @@ find_affinescript_repo() { local candidate for candidate in \ "${AFFINESCRIPT_REPO:-}" \ - "$ROOT_DIR/../nextgen-languages/affinescript" \ - "$ROOT_DIR/../../nextgen-languages/affinescript" \ + "$PROJECT_ROOT/../nextgen-languages/affinescript" \ + "$PROJECT_ROOT/../../nextgen-languages/affinescript" \ "/var/mnt/eclipse/repos/nextgen-languages/affinescript" do [ -n "$candidate" ] || continue @@ -33,19 +36,19 @@ compile_with_affinescript() { if command -v affinescript >/dev/null 2>&1; then echo "Using affinescript from PATH (WASM GC)" - affinescript compile "$ROOT_DIR/src/main.affine" --wasm-gc -o "$TMP_WASM" + affinescript compile "$SCRIPT_DIR/main.affine" --wasm-gc -o "$TMP_WASM" return $? fi if [ -n "$compiler_repo" ] && [ -x "$compiler_repo/_build/default/bin/main.exe" ]; then echo "Using affinescript from $compiler_repo/_build/default/bin/main.exe (WASM GC)" - "$compiler_repo/_build/default/bin/main.exe" compile "$ROOT_DIR/src/main.affine" --wasm-gc -o "$TMP_WASM" + "$compiler_repo/_build/default/bin/main.exe" compile "$SCRIPT_DIR/main.affine" --wasm-gc -o "$TMP_WASM" return $? fi if [ -n "$compiler_repo" ]; then echo "Using dune exec affinescript from $compiler_repo (WASM GC)" - ( cd "$compiler_repo" && dune exec affinescript -- compile "$ROOT_DIR/src/main.affine" --wasm-gc -o "$TMP_WASM" ) + ( cd "$compiler_repo" && dune exec affinescript -- compile "$SCRIPT_DIR/main.affine" --wasm-gc -o "$TMP_WASM" ) return $? fi diff --git a/lib/etma_handler/bouncer.ex b/lib/etma_handler/bouncer.ex index 63f5fdb..e194b6d 100644 --- a/lib/etma_handler/bouncer.ex +++ b/lib/etma_handler/bouncer.ex @@ -4,42 +4,53 @@ defmodule EtmaHandler.Bouncer do @moduledoc """ The Bouncer — Automated Ingestion and Security Gateway. - This module implements a reactive filesystem watcher that monitors - the system Downloads folder for student submissions. It provides a - secure, multi-stage pipeline to transform raw files into verified - ZIP artifacts. + This module is the planned reactive filesystem watcher that monitors the + system Downloads folder for student submissions. The full pipeline is + scheduled for Phase 1.3 (after the FHI parser in Phase 1.2); the module + currently exposes only the filename / extension constants used by other + components and fails loudly if added to the supervision tree. - ## Ingestion Pipeline: - 1. **DETECTION**: Filters for filenames matching the eTMA pattern + ## Planned ingestion pipeline: + 1. **DETECTION**: Filters for filenames matching the eTMA pattern (`[Course]-[Presentation]-[TMA]-[ID]-[OUCU]`). - 2. **SCANNING**: Dispatches the file to the `Scanner` for virus + 2. **SCANNING**: Dispatches the file to the `Scanner` for virus and macro analysis. 3. **QUARANTINE**: Isolates "dirty" or malformed files for manual review. - 4. **PACKAGING**: Encapsulates verified files into an immutable + 4. **PACKAGING**: Encapsulates verified files into an immutable ZIP container within the secure vault. """ use GenServer require Logger - # SUPPORTED TYPES: High-assurance whitelist for student artifacts. @document_extensions ~w(.doc .docx .rtf .odt .pdf .txt) @code_extensions ~w(.ex .rs .js .py .java .c .cpp) @filename_pattern ~r/^([A-Z]{1,4}\d{2,4})-(\d{2}[JBDK])-(\d{2})-(\d+)-([a-z]{2}\d+)/i - @impl true - def init(opts) do - # BOOTSTRAP: Establishes the link to the OS filesystem watcher. - # Ensures that vault and quarantine directories exist. - {:ok, watcher_pid} = FileSystem.start_link(dirs: [download_dir]) - FileSystem.subscribe(watcher_pid) - {:ok, %__MODULE__{...}} + @doc "Compiled regex for valid eTMA filenames." + @spec filename_pattern() :: Regex.t() + def filename_pattern, do: @filename_pattern + + @doc "Document extensions accepted by the ingest pipeline." + @spec document_extensions() :: [String.t()] + def document_extensions, do: @document_extensions + + @doc "Source-code extensions accepted by the ingest pipeline." + @spec code_extensions() :: [String.t()] + def code_extensions, do: @code_extensions + + def start_link(opts \\ []) do + GenServer.start_link(__MODULE__, opts, name: __MODULE__) end @impl true - def handle_call({:ingest, file_path}, _from, state) do - # MANUAL OVERRIDE: Allows the UI to force ingestion of a specific path. - result = do_ingest(file_path, state) - {:reply, result, state} + def init(_opts) do + Logger.error( + "EtmaHandler.Bouncer is not implemented (scheduled for Phase 1.3). " <> + "Set :etma_handler, :auto_ingest to false (default) to remove it from " <> + "the supervision tree." + ) + + {:stop, :not_implemented} end end diff --git a/lib/etma_handler/proven/safe_state_machine.ex b/lib/etma_handler/proven/safe_state_machine.ex index 6ae6c30..80122ff 100644 --- a/lib/etma_handler/proven/safe_state_machine.ex +++ b/lib/etma_handler/proven/safe_state_machine.ex @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: PMPL-1.0 +# SPDX-License-Identifier: MPL-2.0 # SPDX-FileCopyrightText: 2025 Hyperpolymath # # SafeStateMachine - Elixir bindings for proven SafeStateMachine diff --git a/mix.lock b/mix.lock index 933270b..bdd0e33 100644 --- a/mix.lock +++ b/mix.lock @@ -17,7 +17,7 @@ "ex_hash_ring": {:hex, :ex_hash_ring, "6.0.4", "bef9d2d796afbbe25ab5b5a7ed746e06b99c76604f558113c273466d52fa6d6b", [:mix], [], "hexpm", "89adabf31f7d3dfaa36802ce598ce918e9b5b33bae8909ac1a4d052e1e567d18"}, "expo": {:hex, :expo, "1.1.1", "4202e1d2ca6e2b3b63e02f69cfe0a404f77702b041d02b58597c00992b601db5", [:mix], [], "hexpm", "5fb308b9cb359ae200b7e23d37c76978673aa1b06e2b3075d814ce12c5811640"}, "file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"}, - "finch": {:hex, :finch, "0.20.0", "5330aefb6b010f424dcbbc4615d914e9e3deae40095e73ab0c1bb0968933cadf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2658131a74d051aabfcba936093c903b8e89da9a1b63e430bee62045fa9b2ee2"}, + "finch": {:hex, :finch, "0.22.0", "5c48fa6f9706a78eb9036cacb67b8b996b4e66d111c543f4c29bb0f879a6806b", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.8", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b94e83c47780fc6813f746a1f1a34ee65cda42da4c5ea26a68f0acc4498e23dc"}, "floki": {:hex, :floki, "0.38.3", "40d291831d93f49aa360f09447cf2e2a902e33d8711e5fb22a75f3f333e9d063", [:mix], [], "hexpm", "025aa1f5f24a70cb31bfbc7011419228596f3b062d7feda617238ba4926f83cb"}, "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, "guesswork": {:hex, :guesswork, "0.8.0", "fba7e584ed95f10bb083df72cd2a41f8bae3af5731e6b298e72274b764879816", [:mix], [{:kino, "~> 0.13", [hex: :kino, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:stream_split, "~> 0.1.0", [hex: :stream_split, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:uuid, "~> 1.1", [hex: :uuid, repo: "hexpm", optional: false]}], "hexpm", "158b290cda998e2ce95aa11e8f915e84b682f526aa8b3624bbc110f71ad8fea2"}, @@ -27,10 +27,10 @@ "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, "jumper": {:hex, :jumper, "1.0.2", "68cdcd84472a00ac596b4e6459a41b3062d4427cbd4f1e8c8793c5b54f1406a7", [:mix], [], "hexpm", "9b7782409021e01ab3c08270e26f36eb62976a38c1aa64b2eaf6348422f165e1"}, - "kino": {:hex, :kino, "0.18.0", "a1ae60dcbd79413befea7902906be5c6a8f7380af86f86dbdc7994687ad3a13f", [:mix], [{:nx, "~> 0.1", [hex: :nx, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}, {:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "11868c6d653523550ec208c7dc3717fffb68c0380e20fca395251d9db447d1a7"}, + "kino": {:hex, :kino, "0.19.0", "fc8e46fefeb2d083e757633ddd810c499754b7a1f87ba1e92844791c1eca87c2", [:mix], [{:nx, "~> 0.1", [hex: :nx, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}, {:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "195956058730acc397375a398835c7818f92aa01a1d32c03ecb5dffff74c0b8c"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"}, - "mimerl": {:hex, :mimerl, "1.4.0", "3882a5ca67fbbe7117ba8947f27643557adec38fa2307490c4c4207624cb213b", [:rebar3], [], "hexpm", "13af15f9f68c65884ecca3a3891d50a7b57d82152792f3e19d88650aa126b144"}, + "mimerl": {:hex, :mimerl, "1.5.0", "f35aca6f23242339b3666e0ac0702379e362b469d0aea167f6cc713547e777ed", [:rebar3], [], "hexpm", "db648ce065bae14ea84ca8b5dd123f42f49417cef693541110bf6f9e9be9ecc4"}, "mint": {:hex, :mint, "1.8.0", "b964eaf4416f2dee2ba88968d52239fca5621b0402b9c95f55a08eb9d74803e9", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "f3c572c11355eccf00f22275e9b42463bc17bd28db13be1e28f8e0bb4adbc849"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, @@ -45,8 +45,8 @@ "plug": {:hex, :plug, "1.19.2", "e4950525b22c6789dfb38a3f95d47171ba159da3fc5a33be9643b43d5e8adb98", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b6fce20a56af5e60fa5dfecf3f907bb98ec981be43c79a3809a499bc3d133de0"}, "plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"}, "req": {:hex, :req, "0.5.18", "48e6431cb4135e8a7815e745177485369a9b4a9924d5fe68ca00eb09ceaed1ef", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.21.0 or ~> 0.22.0", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "fa03812c440a9754bf34355e0c5d4f3ed316458db62e3284b7a352ef8dc0b996"}, - "rustler": {:hex, :rustler, "0.37.3", "5f4e6634d43b26f0a69834dd1d3ed4e1710b022a053bf4a670220c9540c92602", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "a6872c6f53dcf00486d1e7f9e046e20e01bf1654bdacc4193016c2e8002b32a2"}, - "sleeplocks": {:hex, :sleeplocks, "1.1.3", "96a86460cc33b435c7310dbd27ec82ca2c1f24ae38e34f8edde97f756503441a", [:rebar3], [], "hexpm", "d3b3958552e6eb16f463921e70ae7c767519ef8f5be46d7696cc1ed649421321"}, + "rustler": {:hex, :rustler, "0.38.0", "7a8906998ff0d28e3021c0a73264abcda719bda344b2e58307c6805b0f87c9b4", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "704c03c1bf66be12b031c5a389347b91c81c5cb819a24b068b0de36fe4a5652a"}, + "sleeplocks": {:hex, :sleeplocks, "1.1.4", "be657d2326fad313a9cbc45374dcd861416f2f2097bc71c4de1538b65c7ccc8e", [:rebar3], [], "hexpm", "bc12752ab0693ea4e4a3bcf4e063cef408d71197a3c0fad75497fabd475f5481"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stream_split": {:hex, :stream_split, "0.1.7", "2d3fd1fd21697da7f91926768d65f79409086052c9ec7ae593987388f52425f8", [:mix], [], "hexpm", "1dc072ff507a64404a0ad7af90df97096183fee8eeac7b300320cea7c4679147"}, "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, diff --git a/schemas/config.cue b/schemas/config.cue deleted file mode 100644 index 71e74b4..0000000 --- a/schemas/config.cue +++ /dev/null @@ -1,9 +0,0 @@ -// Configuration schema -package config - -#Config: { - name: string - replicas: int & >=1 - port: int & >=1 & <=65535 - env: string -} diff --git a/test/etma_handler/bouncer_test.exs b/test/etma_handler/bouncer_test.exs index 1ae10f3..1591025 100644 --- a/test/etma_handler/bouncer_test.exs +++ b/test/etma_handler/bouncer_test.exs @@ -6,16 +6,14 @@ defmodule EtmaHandler.BouncerTest do describe "filename validation" do test "accepts valid OU filename format" do - # Test the internal validation via the public API when bouncer is running - # For now, test the pattern matching logic directly - pattern = ~r/^([A-Z]{1,4}\d{2,4})-(\d{2}[JB])-(\d{2})-(\d+)-([a-z]{2}\d+)/i + pattern = Bouncer.filename_pattern() assert Regex.match?(pattern, "M150-25J-01-1-rg8274") assert Regex.match?(pattern, "TM470-25B-02-5-ab1234") end test "rejects invalid filename format" do - pattern = ~r/^([A-Z]{1,4}\d{2,4})-(\d{2}[JB])-(\d{2})-(\d+)-([a-z]{2}\d+)/i + pattern = Bouncer.filename_pattern() refute Regex.match?(pattern, "invalid-filename") refute Regex.match?(pattern, "M150_25J_01_1_rg8274") @@ -24,34 +22,42 @@ defmodule EtmaHandler.BouncerTest do end describe "extension validation" do - @allowed_extensions ~w(.doc .docx .rtf .pdf .zip .fhi .odt) + test "document extensions are exposed" do + docs = Bouncer.document_extensions() - test "accepts allowed extensions" do - for ext <- @allowed_extensions do - assert ext in @allowed_extensions - end + assert ".docx" in docs + assert ".pdf" in docs + assert ".odt" in docs end - test "rejects disallowed extensions" do - refute ".exe" in @allowed_extensions - refute ".bat" in @allowed_extensions - refute ".js" in @allowed_extensions + test "code extensions are exposed" do + code = Bouncer.code_extensions() + + assert ".ex" in code + assert ".rs" in code + end + + test "executables are not in any allowlist" do + all = Bouncer.document_extensions() ++ Bouncer.code_extensions() + + refute ".exe" in all + refute ".bat" in all + refute ".sh" in all end end describe "metadata extraction" do test "extracts metadata from valid filename" do - # The filename pattern extracts: - # - course code (M150) - # - presentation (25J) - # - TMA number (01) - # - submission ID (1) - # - student OUCU (rg8274) - pattern = ~r/^([A-Z]{1,4}\d{2,4})-(\d{2}[JB])-(\d{2})-(\d+)-([a-z]{2}\d+)/i - - captures = Regex.run(pattern, "M150-25J-01-1-rg8274") + # course code, presentation, TMA number, submission ID, student OUCU + captures = Regex.run(Bouncer.filename_pattern(), "M150-25J-01-1-rg8274") assert captures == ["M150-25J-01-1-rg8274", "M150", "25J", "01", "1", "rg8274"] end end + + describe "supervision tree behaviour" do + test "init/1 stops with :not_implemented" do + assert {:stop, :not_implemented} = Bouncer.init([]) + end + end end diff --git a/tests/fuzz/placeholder.txt b/test/fuzz/.gitkeep similarity index 100% rename from tests/fuzz/placeholder.txt rename to test/fuzz/.gitkeep diff --git a/well-known-template.tar.gz b/well-known-template.tar.gz deleted file mode 100644 index b615109..0000000 Binary files a/well-known-template.tar.gz and /dev/null differ diff --git a/well-known-template/.well-known/ai.txt b/well-known-template/.well-known/ai.txt deleted file mode 100644 index 546b4b0..0000000 --- a/well-known-template/.well-known/ai.txt +++ /dev/null @@ -1,21 +0,0 @@ -# AI Policy -# Human-readable version of aibdp.json - -# Permissions -Training: allowed with attribution -Indexing: allowed -Scraping: allowed (respect robots.txt) -Summarization: allowed -Code-Generation: allowed with license compliance - -# Attribution -Required: yes -Format: "PROJECT_NAME (LICENSE)" - -# Contact -Questions: CONTACT_URL - -# See also -# /.well-known/aibdp.json - Machine-readable declaration -# /llms.txt - LLM context -# /robots.txt - Crawler directives diff --git a/well-known-template/.well-known/aibdp.json b/well-known-template/.well-known/aibdp.json deleted file mode 100644 index 56479da..0000000 --- a/well-known-template/.well-known/aibdp.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "$schema": "https://consent-aware.org/schemas/aibdp/v1.json", - "version": "1.0", - "protocol": "AI Boundary Declaration Protocol", - "issued": "YYYY-MM-DD", - "expires": "YYYY-MM-DD", - - "identity": { - "name": "PROJECT_NAME", - "type": "open-source-project", - "url": "https://YOURDOMAIN.example", - "license": "LICENSE_SPDX_ID" - }, - - "boundaries": { - "training": { - "permitted": true, - "conditions": ["attribution", "license-compliance"] - }, - "inference": { - "permitted": true, - "conditions": [] - }, - "indexing": { - "permitted": true - }, - "scraping": { - "permitted": true, - "respect_robots_txt": true - }, - "embedding": { - "permitted": true, - "conditions": ["attribution"] - } - }, - - "consent": { - "default": "permit-with-conditions", - "withdrawal_contact": "CONTACT_EMAIL_OR_URL" - }, - - "attribution": { - "required": true, - "format": "PROJECT_NAME (LICENSE)" - }, - - "related": { - "robots_txt": "/robots.txt", - "llms_txt": "/llms.txt", - "license": "/LICENSE" - } -} diff --git a/well-known-template/.well-known/apple-app-site-association b/well-known-template/.well-known/apple-app-site-association deleted file mode 100644 index 696bb79..0000000 --- a/well-known-template/.well-known/apple-app-site-association +++ /dev/null @@ -1,14 +0,0 @@ -{ - "applinks": { - "apps": [], - "details": [ - { - "appID": "TEAMID.com.example.app", - "paths": ["*"] - } - ] - }, - "webcredentials": { - "apps": ["TEAMID.com.example.app"] - } -} diff --git a/well-known-template/.well-known/assetlinks.json b/well-known-template/.well-known/assetlinks.json deleted file mode 100644 index ffdbff7..0000000 --- a/well-known-template/.well-known/assetlinks.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "relation": ["delegate_permission/common.handle_all_urls"], - "target": { - "namespace": "android_app", - "package_name": "com.example.app", - "sha256_cert_fingerprints": [ - "SHA256_FINGERPRINT_HERE" - ] - } - } -] diff --git a/well-known-template/.well-known/atproto-did b/well-known-template/.well-known/atproto-did deleted file mode 100644 index 5f2609d..0000000 --- a/well-known-template/.well-known/atproto-did +++ /dev/null @@ -1 +0,0 @@ -did:plc:YOUR_BLUESKY_DID_HERE diff --git a/well-known-template/.well-known/change-password b/well-known-template/.well-known/change-password deleted file mode 100644 index d37af0f..0000000 --- a/well-known-template/.well-known/change-password +++ /dev/null @@ -1 +0,0 @@ -https://YOURDOMAIN.example/account/password diff --git a/well-known-template/.well-known/consent-required.txt b/well-known-template/.well-known/consent-required.txt deleted file mode 100644 index 1a9bbc7..0000000 --- a/well-known-template/.well-known/consent-required.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Consent Requirements - -## Data Processed -- [Describe what data this project/site handles] - -## Consent Basis -| Data Type | Consent Required | Legal Basis | -|-----------|------------------|-------------| -| Example | Yes/No | Legitimate interest / Consent / Contract | - -## User Rights -- Export data: [URL or process] -- Delete data: [URL or process] -- Withdraw consent: [URL or process] - -## Contact -Privacy inquiries: CONTACT_URL diff --git a/well-known-template/.well-known/did.json b/well-known-template/.well-known/did.json deleted file mode 100644 index b6a14dd..0000000 --- a/well-known-template/.well-known/did.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:web:YOURDOMAIN.example", - "alsoKnownAs": [ - "https://YOURDOMAIN.example" - ], - "service": [ - { - "id": "#website", - "type": "LinkedDomains", - "serviceEndpoint": "https://YOURDOMAIN.example" - } - ] -} diff --git a/well-known-template/.well-known/gpc.json b/well-known-template/.well-known/gpc.json deleted file mode 100644 index 74acd1d..0000000 --- a/well-known-template/.well-known/gpc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "gpc": true, - "lastUpdate": "YYYY-MM-DD" -} diff --git a/well-known-template/.well-known/host-meta b/well-known-template/.well-known/host-meta deleted file mode 100644 index f4c8d3d..0000000 --- a/well-known-template/.well-known/host-meta +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/well-known-template/.well-known/humans.txt b/well-known-template/.well-known/humans.txt deleted file mode 100644 index af09b27..0000000 --- a/well-known-template/.well-known/humans.txt +++ /dev/null @@ -1,10 +0,0 @@ -/* TEAM */ -Project: PROJECT_NAME -Site: https://YOURDOMAIN.example - -/* THANKS */ -Contributors: /humans.txt or /CONTRIBUTORS - -/* SITE */ -Standards: HTML5, CSS3 -Software: YOUR_STACK diff --git a/well-known-template/.well-known/jwks.json b/well-known-template/.well-known/jwks.json deleted file mode 100644 index 83b2ad9..0000000 --- a/well-known-template/.well-known/jwks.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "keys": [ - { - "kty": "RSA", - "use": "sig", - "alg": "RS256", - "kid": "KEY_ID", - "n": "BASE64_MODULUS", - "e": "AQAB" - } - ] -} diff --git a/well-known-template/.well-known/keybase.txt b/well-known-template/.well-known/keybase.txt deleted file mode 100644 index 50990f7..0000000 --- a/well-known-template/.well-known/keybase.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Keybase proof placeholder -# Keybase was acquired by Zoom (2020) and abandoned. -# -# For identity verification, see: -# - /.well-known/did.json -# - /.well-known/webfinger -# -# RIP Keybase (2014-2020) diff --git a/well-known-template/.well-known/matrix/client b/well-known-template/.well-known/matrix/client deleted file mode 100644 index 1ebae6f..0000000 --- a/well-known-template/.well-known/matrix/client +++ /dev/null @@ -1,8 +0,0 @@ -{ - "m.homeserver": { - "base_url": "https://matrix.YOURDOMAIN.example" - }, - "m.identity_server": { - "base_url": "https://vector.im" - } -} diff --git a/well-known-template/.well-known/matrix/server b/well-known-template/.well-known/matrix/server deleted file mode 100644 index 9f68ab4..0000000 --- a/well-known-template/.well-known/matrix/server +++ /dev/null @@ -1,3 +0,0 @@ -{ - "m.server": "matrix.YOURDOMAIN.example:443" -} diff --git a/well-known-template/.well-known/nodeinfo b/well-known-template/.well-known/nodeinfo deleted file mode 100644 index f23945d..0000000 --- a/well-known-template/.well-known/nodeinfo +++ /dev/null @@ -1,8 +0,0 @@ -{ - "links": [ - { - "rel": "http://nodeinfo.diaspora.software/ns/schema/2.1", - "href": "https://YOURDOMAIN.example/nodeinfo/2.1" - } - ] -} diff --git a/well-known-template/.well-known/nostr.json b/well-known-template/.well-known/nostr.json deleted file mode 100644 index 5b65c3a..0000000 --- a/well-known-template/.well-known/nostr.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "names": { - "_": "NPUB_HEX_WITHOUT_NPUB_PREFIX" - }, - "relays": { - "NPUB_HEX": ["wss://relay.example.com"] - } -} diff --git a/well-known-template/.well-known/openid-configuration b/well-known-template/.well-known/openid-configuration deleted file mode 100644 index 924547e..0000000 --- a/well-known-template/.well-known/openid-configuration +++ /dev/null @@ -1,10 +0,0 @@ -{ - "issuer": "https://YOURDOMAIN.example", - "authorization_endpoint": "https://YOURDOMAIN.example/oauth/authorize", - "token_endpoint": "https://YOURDOMAIN.example/oauth/token", - "userinfo_endpoint": "https://YOURDOMAIN.example/oauth/userinfo", - "jwks_uri": "https://YOURDOMAIN.example/.well-known/jwks.json", - "response_types_supported": ["code", "token", "id_token"], - "subject_types_supported": ["public"], - "id_token_signing_alg_values_supported": ["RS256"] -} diff --git a/well-known-template/.well-known/provenance.json b/well-known-template/.well-known/provenance.json deleted file mode 100644 index e9bd5f5..0000000 --- a/well-known-template/.well-known/provenance.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "version": "1.0", - "project": "PROJECT_NAME", - "repository": "https://github.com/USER/REPO", - "license": "LICENSE_SPDX_ID", - "build": { - "reproducible": true, - "system": "BUILD_SYSTEM" - } -} diff --git a/well-known-template/.well-known/security.txt b/well-known-template/.well-known/security.txt deleted file mode 100644 index 7656743..0000000 --- a/well-known-template/.well-known/security.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Security Contact -# RFC 9116 - https://securitytxt.org/ - -Contact: mailto:security@YOURDOMAIN.example -Expires: YYYY-12-31T23:59:59.000Z -Preferred-Languages: en -Canonical: https://YOURDOMAIN.example/.well-known/security.txt -Policy: https://YOURDOMAIN.example/security-policy - -# Optional -# Encryption: https://YOURDOMAIN.example/.well-known/pgp-key.txt -# Acknowledgments: https://YOURDOMAIN.example/security-thanks -# Hiring: https://YOURDOMAIN.example/security-jobs diff --git a/well-known-template/.well-known/webfinger b/well-known-template/.well-known/webfinger deleted file mode 100644 index f0b120e..0000000 --- a/well-known-template/.well-known/webfinger +++ /dev/null @@ -1,18 +0,0 @@ -{ - "subject": "acct:HANDLE@DOMAIN.example", - "aliases": [ - "https://YOURDOMAIN.example" - ], - "links": [ - { - "rel": "http://webfinger.net/rel/profile-page", - "type": "text/html", - "href": "https://YOURDOMAIN.example" - }, - { - "rel": "self", - "type": "application/activity+json", - "href": "https://YOURDOMAIN.example/activitypub" - } - ] -} diff --git a/well-known-template/README.md b/well-known-template/README.md deleted file mode 100644 index 2d0b55b..0000000 --- a/well-known-template/README.md +++ /dev/null @@ -1,116 +0,0 @@ -# .well-known Template - -A comprehensive template for web identity, consent, and discovery standards. - -## Quick Start - -```bash -cp -r .well-known /your/project/ -cp robots.txt llms.txt ads.txt /your/project/ -# Edit files to match your project -``` - -## File Inventory - -### Security & Trust - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/security.txt` | RFC 9116 | Active | Security contact & disclosure policy | -| `.well-known/pgp-key.txt` | - | Active | PGP public key for encrypted reports | -| `robots.txt` | RFC 9309 | Active | Crawler directives | - -### AI & Consent (Emerging) - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/aibdp.json` | AIBDP | Draft | AI Boundary Declaration Protocol | -| `.well-known/ai.txt` | - | Informal | Simple AI policy (human-readable) | -| `.well-known/consent-required.txt` | - | Draft | Data handling consent requirements | -| `llms.txt` | llmstxt.org | Informal | LLM context file | - -### Identity & Discovery - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/webfinger` | RFC 7033 | Active | User/resource discovery | -| `.well-known/host-meta` | RFC 6415 | Active | Host metadata (XRD) | -| `.well-known/did.json` | W3C DID | Active | Decentralized Identifier | -| `.well-known/keybase.txt` | - | Dead | Keybase proof (RIP) | -| `.well-known/nostr.json` | NIP-05 | Active | Nostr identity verification | -| `.well-known/atproto-did` | AT Protocol | Active | Bluesky DID | -| `.well-known/matrix/server` | Matrix | Active | Matrix server discovery | -| `.well-known/matrix/client` | Matrix | Active | Matrix client discovery | -| `.well-known/nodeinfo` | NodeInfo | Active | Federated network metadata | -| `.well-known/avatar` | - | Informal | Avatar URL | - -### Authentication & Authorization - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/openid-configuration` | OIDC | Active | OpenID Connect discovery | -| `.well-known/oauth-authorization-server` | RFC 8414 | Active | OAuth server metadata | -| `.well-known/jwks.json` | RFC 7517 | Active | JSON Web Key Set | -| `.well-known/change-password` | - | Active | Password change URL hint | - -### Advertising & Monetization - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `ads.txt` | IAB | Active | Authorized digital sellers | -| `sellers.json` | IAB | Active | Seller information | -| `app-ads.txt` | IAB | Active | Mobile app ad sellers | - -### Mobile & Apps - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/assetlinks.json` | Google | Active | Android App Links | -| `.well-known/apple-app-site-association` | Apple | Active | iOS Universal Links | - -### Privacy & Legal - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/dnt-policy.txt` | EFF | Abandoned | Do Not Track policy | -| `.well-known/gpc.json` | GPC | Active | Global Privacy Control | -| `.well-known/privacy-policy` | - | Informal | Privacy policy redirect | - -### Provenance & Supply Chain - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/provenance.json` | - | Draft | Build/source provenance | -| `sbom.json` | CycloneDX/SPDX | Active | Software Bill of Materials | - -### Miscellaneous - -| File | Standard | Status | Purpose | -|------|----------|--------|---------| -| `.well-known/humans.txt` | humanstxt.org | Active | Project credits | -| `.well-known/traffic-advice` | Chrome | Active | Speculation rules | -| `.well-known/core` | RFC 6690 | Active | CoRE link format (IoT) | - -## The Graveyard - -Standards that died so others could... also die: - -- **Keybase** - Zoom acquisition (2020) -- **Persona/BrowserID** - Mozilla gave up (2016) -- **OpenID 1.0/2.0** - Replaced by OIDC -- **DNT** - Browser vendors abandoned it -- **P3P** - IE-only, XML nightmare -- **XRI/XRD** - Overcomplicated into irrelevance - -## Philosophy - -This template exists because: - -1. **Silence is consent** - AI companies interpret missing declarations as permission -2. **Standards fragment** - Everyone wants to own the spec -3. **Dead protocols leave ghosts** - Keybase proofs still get checked -4. **Defense in depth** - Multiple declarations, multiple chances to be heard - -## License - -CC0 / Public Domain - Use however you want. diff --git a/well-known-template/ads.txt b/well-known-template/ads.txt deleted file mode 100644 index 4a99a0b..0000000 --- a/well-known-template/ads.txt +++ /dev/null @@ -1,8 +0,0 @@ -# ads.txt - Authorized Digital Sellers -# https://iabtechlab.com/ads-txt/ - -# This project/site does not participate in programmatic advertising. -# No authorized sellers. - -# If you DO have ad partners, format is: -# domain.com, publisher-id, DIRECT/RESELLER, certification-id diff --git a/well-known-template/llms.txt b/well-known-template/llms.txt deleted file mode 100644 index a3a507c..0000000 --- a/well-known-template/llms.txt +++ /dev/null @@ -1,23 +0,0 @@ -# PROJECT_NAME - LLM Context -# https://llmstxt.org/ - -> Brief description of the project. - -## Overview - -- **Purpose**: What it does -- **Stack**: Technologies used -- **License**: LICENSE_NAME - -## Key Files - -- `/path/to/important/` - Description -- `/another/path/` - Description - -## For AI Assistants - -Guidance for AI working on this codebase. - -## Boundaries - -See `/.well-known/aibdp.json` for full AI boundary declaration. diff --git a/well-known-template/robots.txt b/well-known-template/robots.txt deleted file mode 100644 index b95a278..0000000 --- a/well-known-template/robots.txt +++ /dev/null @@ -1,34 +0,0 @@ -# robots.txt - -User-agent: * -Allow: / - -# AI crawlers (explicit declaration) -User-agent: GPTBot -Allow: / - -User-agent: ChatGPT-User -Allow: / - -User-agent: Google-Extended -Allow: / - -User-agent: CCBot -Allow: / - -User-agent: anthropic-ai -Allow: / - -User-agent: Claude-Web -Allow: / - -# Disallow if needed -# User-agent: SomeBot -# Disallow: /private/ - -# Advisory rate limit -Crawl-delay: 1 - -# Related -# AI Boundary Declaration: /.well-known/aibdp.json -# LLM Context: /llms.txt diff --git a/well-known-template/sellers.json b/well-known-template/sellers.json deleted file mode 100644 index 8a96c06..0000000 --- a/well-known-template/sellers.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "contact_email": "ads@YOURDOMAIN.example", - "contact_address": "", - "version": "1.0", - "identifiers": [], - "sellers": [] -}