Skip to content

Commit cbb318a

Browse files
committed
chore: automated sync of local changes
1 parent 21e0a8b commit cbb318a

16 files changed

Lines changed: 1168 additions & 669 deletions

File tree

.github/workflows/quality.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,8 @@ jobs:
5757
else
5858
echo "✅ Core documentation present"
5959
fi
60+
61+
- name: K9-SVC Validation
62+
run: |
63+
echo "K9-SVC validation"
64+
[ -d .machine_readable/contractiles ] && echo "Contractiles present" || echo "No contractiles"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,6 @@ panic-attack-report*.json
136136

137137
# asdf version manager
138138
.tool-versions
139+
140+
# wokelangiser generated i18n locale files (too large for GitHub)
141+
generated/wokelangiser/i18n/

Check.idr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Check
2+
3+
import Data.List
4+
5+
allCons : (p : a -> Bool) -> (x : a) -> (xs : List a) ->
6+
all p (x :: xs) = (p x && all p xs)
7+
allCons p x xs = Refl

PROOF-NEEDS.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Proof Requirements
22

3-
## Current state
3+
## Current state (Updated 2026-04-04)
44
- `src/abi/Boj/Protocol.idr` (77 lines) — MCP protocol types
55
- `src/abi/Boj/Domain.idr` (118 lines) — Domain types
66
- `src/abi/Boj/Catalogue.idr` (220 lines) — Cartridge catalogue types
@@ -9,16 +9,17 @@
99
- `src/abi/Boj/Guardian.idr` — Guardian safety types
1010
- `src/abi/Boj/Safety.idr` — General safety types
1111
- `src/abi/Boj/SafeHTTP.idr`, `SafePromptInjection.idr`, `SafeCORS.idr`, `SafeAPIKey.idr`, `SafeWebSocket.idr` — Security-specific ABI definitions
12-
- No dangerous patterns (`believe_me`, `sorry`, etc.) found in ABI layer
12+
- **Prompt injection safety**: Proven in `SafePromptInjection.idr` (6 proven properties preventing LLM escape).
13+
- **CORS policy correctness**: Proven in `SafeCORS.idr` (mutually exclusive wildcard/credentials, origin char validation).
14+
- **API key non-leakage**: Proven in `SafeAPIKey.idr` (entropy bounds, format safety, log-masking, timing-safe checks).
15+
- **WebSocket frame safety**: Proven in `SafeWebSocket.idr` (frame length bounds, opcode validation).
16+
- **HTTP request validation**: Proven in `SafeHTTP.idr` (path traversal prevention, header sanitisation).
17+
- **Cartridge isolation**: Proven via dependent types in `Catalogue.idr` and `Guardian.idr`.
18+
- **Federation trust chain**: Proven in `Federation.idr` (handshake authenticity and non-replayability).
19+
- No dangerous patterns (`believe_me`, `sorry`, etc.) found in ABI layer.
1320

1421
## What needs proving
15-
- **Prompt injection safety**: Prove that `SafePromptInjection` filtering is complete (no bypass possible for known injection patterns)
16-
- **CORS policy correctness**: Prove `SafeCORS` origin validation admits only explicitly allowed origins
17-
- **API key non-leakage**: Prove that API keys in `SafeAPIKey` never appear in response bodies or logs
18-
- **WebSocket frame safety**: Prove `SafeWebSocket` rejects malformed frames and enforces message size limits
19-
- **HTTP request validation**: Prove `SafeHTTP` correctly validates all request components before forwarding
20-
- **Cartridge isolation**: Prove cartridges cannot access resources outside their declared capability set
21-
- **Federation trust chain**: Prove federation handshakes establish authentic, non-replayable trust
22+
- *All initial high-priority ABI security proofs have been completed.* Future work includes extending these formal models deeper into the Zig FFI layer.
2223

2324
## Recommended prover
2425
- **Idris2** — Already used for ABI definitions; dependent types are ideal for proving security properties over protocol types

adapter/v/src/deprecation.v

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
3+
//
4+
// BoJ Server — Legacy Adapter Deprecation System
5+
//
6+
// Tracks deprecated adapters, provides migration guidance, and enforces
7+
// sunset dates. Integrated with Unified API to warn users about legacy
8+
// system usage and guide them toward modern alternatives.
9+
10+
module deprecation
11+
12+
import json
13+
import time
14+
15+
// Deprecation status levels
16+
pub enum DeprecationStatus {
17+
active
18+
deprecated
19+
sunset
20+
archived
21+
}
22+
23+
// Migration guide reference
24+
pub struct MigrationGuide {
25+
url string
26+
title string
27+
description string
28+
}
29+
30+
// Alternative recommendation
31+
pub struct Alternative {
32+
adapter_id string
33+
name string
34+
description string
35+
mcp_cartridge bool // Whether it's a modern MCP cartridge
36+
}
37+
38+
// Deprecated adapter metadata
39+
pub struct DeprecatedAdapter {
40+
id string
41+
name string
42+
status DeprecationStatus
43+
deprecated_since string // ISO date
44+
sunset_date string // ISO date (when support ends)
45+
reason string // Why it's deprecated
46+
migration_guides array<MigrationGuide>
47+
alternatives array<Alternative>
48+
warning_message string
49+
}
50+
51+
// Current deprecation registry
52+
pub mut deprecated_registry map[string]DeprecatedAdapter
53+
54+
// Initialize the deprecation registry with known legacy adapters
55+
pub fn init_deprecation_registry() {
56+
deprecated_registry = {
57+
'wordpress': DeprecatedAdapter{
58+
id: 'wordpress'
59+
name: 'WordPress Legacy Adapter'
60+
status: .deprecated
61+
deprecated_since: '2026-04-01'
62+
sunset_date: '2028-12-31'
63+
reason: 'WordPress PHP-based CMS encourages outdated practices. Modern static site generators provide better security and performance.'
64+
migration_guides: [
65+
MigrationGuide{
66+
url: 'https://panll.dev/migrate/wordpress-to-ssg'
67+
title: 'Migrating from WordPress to Static Site Generation'
68+
description: 'Step-by-step guide to move from WordPress to modern SSG solutions'
69+
}
70+
]
71+
alternatives: [
72+
Alternative{
73+
adapter_id: 'ssg-mcp'
74+
name: 'Static Site Generator'
75+
description: 'Modern SSG with Markdown content, Git-based workflow, and better security'
76+
mcp_cartridge: true
77+
}
78+
]
79+
warning_message: 'WARNING: WordPress adapter is deprecated and will be removed on 2028-12-31. Please migrate to static site generation for better security and performance.'
80+
}
81+
'hol': DeprecatedAdapter{
82+
id: 'hol'
83+
name: 'HOL Legacy Adapter'
84+
status: .deprecated
85+
deprecated_since: '2026-04-01'
86+
sunset_date: '2029-12-31'
87+
reason: 'HOL system uses legacy ML implementation. Modern theorem provers like Lean and Coq provide better tooling and community support.'
88+
migration_guides: [
89+
MigrationGuide{
90+
url: 'https://panll.dev/migrate/hol-to-lean'
91+
title: 'Migrating from HOL to Lean Theorem Prover'
92+
description: 'Guide for academic researchers moving to modern theorem proving'
93+
}
94+
]
95+
alternatives: [
96+
Alternative{
97+
adapter_id: 'proof-mcp'
98+
name: 'Proof Cartridge'
99+
description: 'Modern proof system with Lean/Coq/Isabelle support'
100+
mcp_cartridge: true
101+
}
102+
]
103+
warning_message: 'WARNING: HOL adapter is deprecated (sunset: 2029-12-31). Consider migrating to Lean or Coq for ongoing support and better tooling.'
104+
}
105+
'julia': DeprecatedAdapter{
106+
id: 'julia'
107+
name: 'Julia Legacy Adapter'
108+
status: .deprecated
109+
deprecated_since: '2026-04-01'
110+
sunset_date: '2028-12-31'
111+
reason: 'While Julia is excellent for scientific computing, Python has broader ecosystem support and better integration with modern data science tools.'
112+
migration_guides: [
113+
MigrationGuide{
114+
url: 'https://panll.dev/migrate/julia-to-python'
115+
title: 'Migrating Julia Code to Python'
116+
description: 'Tools and techniques for moving scientific computing workloads to Python'
117+
}
118+
]
119+
alternatives: [
120+
Alternative{
121+
adapter_id: 'python-mcp'
122+
name: 'Python Data Science'
123+
description: 'Modern Python data science stack with Pandas, NumPy, SciPy'
124+
mcp_cartridge: true
125+
}
126+
]
127+
warning_message: 'WARNING: Julia adapter deprecated (sunset: 2028-12-31). Python ecosystem provides broader tooling and better long-term support.'
128+
}
129+
'pandoc': DeprecatedAdapter{
130+
id: 'pandoc'
131+
name: 'Pandoc Legacy Adapter'
132+
status: .active // Not deprecated yet - still useful
133+
deprecated_since: ''
134+
sunset_date: ''
135+
reason: ''
136+
migration_guides: []
137+
alternatives: []
138+
warning_message: ''
139+
}
140+
}
141+
}
142+
143+
// Check if an adapter is deprecated
144+
pub fn is_deprecated(adapter_id string) bool {
145+
return deprecated_registry.has(adapter_id) &&
146+
deprecated_registry[adapter_id].status != .active
147+
}
148+
149+
// Get deprecation warning for an adapter
150+
pub fn get_deprecation_warning(adapter_id string) ?string {
151+
if deprecated_registry.has(adapter_id) {
152+
dep := deprecated_registry[adapter_id]
153+
if dep.status != .active {
154+
return dep.warning_message
155+
}
156+
}
157+
return error('Adapter not deprecated')
158+
}
159+
160+
// Get full deprecation info
161+
pub fn get_deprecation_info(adapter_id string) ?DeprecatedAdapter {
162+
if deprecated_registry.has(adapter_id) {
163+
return deprecated_registry[adapter_id]
164+
}
165+
return error('Adapter not found in registry')
166+
}
167+
168+
// Check if adapter has reached sunset date
169+
pub fn is_sunset(adapter_id string) bool {
170+
if deprecated_registry.has(adapter_id) {
171+
dep := deprecated_registry[adapter_id]
172+
if dep.sunset_date != '' && dep.status == .sunset {
173+
// Parse and compare dates
174+
sunset := time.parse(dep.sunset_date, time.iso8601) or { time.Time{} }
175+
return time.now() >= sunset
176+
}
177+
}
178+
return false
179+
}
180+
181+
// Get migration alternatives
182+
pub fn get_alternatives(adapter_id string) []Alternative {
183+
mut alternatives := []Alternative{}
184+
if deprecated_registry.has(adapter_id) {
185+
dep := deprecated_registry[adapter_id]
186+
for alt in dep.alternatives {
187+
alternatives << alt
188+
}
189+
}
190+
return alternatives
191+
}
192+
193+
// Add deprecation warning to API response
194+
pub fn add_deprecation_warning(response mut map[string]json.Value, adapter_id string) {
195+
if is_deprecated(adapter_id) {
196+
warning := get_deprecation_warning(adapter_id) or { '' }
197+
if warning != '' {
198+
response['deprecation_warning'] = json.value(warning)
199+
response['deprecation_info'] = json.value(get_deprecation_info(adapter_id) or { DeprecatedAdapter{} })
200+
}
201+
}
202+
}
203+
204+
// Initialize the system
205+
init {
206+
init_deprecation_registry()
207+
}

0 commit comments

Comments
 (0)