mirror of
https://github.com/Such-Software/adaptive-multi-protocol-gateway.git
synced 2026-10-17 07:31:32 +02:00
Harden public docs gates
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
> Status: draft | Updated 2026-07-07 | Applies to: AMPG core
|
> Status: draft | Updated 2026-07-11 | Applies to: AMPG core
|
||||||
|
|
||||||
AMPG is a compiler plus an ingress manager. The compiler turns one site into a
|
AMPG is a compiler plus an ingress manager. The compiler turns one site into a
|
||||||
protocol-neutral content graph, then renders protocol-specific outputs. The ingress
|
protocol-neutral content graph, then renders protocol-specific outputs. The ingress
|
||||||
@@ -194,8 +194,10 @@ v1 is static-first, but the architecture reserves a path for interactive applica
|
|||||||
Interactivity is declared per route group:
|
Interactivity is declared per route group:
|
||||||
|
|
||||||
- `static`: files only.
|
- `static`: files only.
|
||||||
- `forms`: server-rendered actions and full-page responses.
|
- `interactive-lite`: deterministic games, status lookups, quote forms, and other flows
|
||||||
- `sessions`: authenticated flows with strict session policy.
|
without account state or payment confirmation.
|
||||||
|
- `identity`: authenticated sessions, wallet sign-in, or signed capability links.
|
||||||
|
- `transactional`: server-confirmed orders, deposits, invoices, donations, or payment intents.
|
||||||
- `realtime`: rich browser/admin interfaces; HTTP transports only.
|
- `realtime`: rich browser/admin interfaces; HTTP transports only.
|
||||||
- `internal`: workers, webhooks, private admin APIs; never published automatically.
|
- `internal`: workers, webhooks, private admin APIs; never published automatically.
|
||||||
|
|
||||||
|
|||||||
+9
-5
@@ -1,6 +1,6 @@
|
|||||||
# Autodocs And Drift Gates
|
# Autodocs And Drift Gates
|
||||||
|
|
||||||
> Status: draft | Updated 2026-07-05 | Applies to: AMPG generated docs
|
> Status: draft | Updated 2026-07-11 | Applies to: AMPG generated docs
|
||||||
|
|
||||||
AMPG should publish concise hand-written docs and generate the parts that can drift from
|
AMPG should publish concise hand-written docs and generate the parts that can drift from
|
||||||
code. Generated artifacts are committed, then checked in CI by regenerating and diffing.
|
code. Generated artifacts are committed, then checked in CI by regenerating and diffing.
|
||||||
@@ -38,13 +38,17 @@ git diff --exit-code docs/generated schemas openapi.json
|
|||||||
python3 tools/docs_check.py
|
python3 tools/docs_check.py
|
||||||
```
|
```
|
||||||
|
|
||||||
`ampg docs check` should verify:
|
`python3 tools/docs_check.py` verifies:
|
||||||
|
|
||||||
- every Markdown file starts with a `> Status:` header.
|
- every Markdown file starts with a `> Status:` header.
|
||||||
- internal links resolve.
|
- internal links resolve.
|
||||||
- generated docs are not edited by hand.
|
- local links stay inside the repository.
|
||||||
- public docs contain no private keys, onion keys, I2P keys, Reticulum identities, or
|
- public docs do not name private fixture targets.
|
||||||
local production secrets.
|
- public docs do not contain obvious private-key blocks, common API tokens, or assigned
|
||||||
|
secret values.
|
||||||
|
|
||||||
|
`python3 -m ampg docs generate --check` verifies that generated docs and schemas match
|
||||||
|
the code-owned metadata.
|
||||||
|
|
||||||
## Public/private boundary
|
## Public/private boundary
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,26 @@ from urllib.parse import unquote
|
|||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
LINK_RE = re.compile(r"(?<!!)\[[^\]]+\]\(([^)]+)\)")
|
LINK_RE = re.compile(r"(?<!!)\[[^\]]+\]\(([^)]+)\)")
|
||||||
|
FORBIDDEN_PUBLIC_TERMS = (
|
||||||
|
"wowrace",
|
||||||
|
"wowngeon",
|
||||||
|
"smirk-monorepo",
|
||||||
|
"medusa-multi-tenant-platform",
|
||||||
|
"ai-gen-bot",
|
||||||
|
)
|
||||||
|
SECRET_PATTERNS = (
|
||||||
|
("private key block", re.compile(r"-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----")),
|
||||||
|
("open ssh private key block", re.compile(r"-----BEGIN OPENSSH PRIVATE KEY-----")),
|
||||||
|
("aws access key", re.compile(r"\bAKIA[0-9A-Z]{16}\b")),
|
||||||
|
("github token", re.compile(r"\bgh[pousr]_[A-Za-z0-9_]{20,}\b")),
|
||||||
|
("slack token", re.compile(r"\bxox[baprs]-[A-Za-z0-9-]{10,}\b")),
|
||||||
|
(
|
||||||
|
"assigned secret",
|
||||||
|
re.compile(
|
||||||
|
r"(?i)\b(api[_-]?key|secret|password|token)\s*=\s*['\"][^'\"]{8,}['\"]"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def iter_markdown() -> list[Path]:
|
def iter_markdown() -> list[Path]:
|
||||||
@@ -50,12 +70,24 @@ def main() -> int:
|
|||||||
text = path.read_text(encoding="utf-8")
|
text = path.read_text(encoding="utf-8")
|
||||||
if not has_status_header(text):
|
if not has_status_header(text):
|
||||||
errors.append(f"{rel}: missing > Status: header in first 6 lines")
|
errors.append(f"{rel}: missing > Status: header in first 6 lines")
|
||||||
|
lower_text = text.lower()
|
||||||
|
for term in FORBIDDEN_PUBLIC_TERMS:
|
||||||
|
if term in lower_text:
|
||||||
|
errors.append(f"{rel}: public docs contain private target term {term!r}")
|
||||||
|
for label, pattern in SECRET_PATTERNS:
|
||||||
|
if pattern.search(text):
|
||||||
|
errors.append(f"{rel}: public docs may contain {label}")
|
||||||
|
|
||||||
for match in LINK_RE.finditer(text):
|
for match in LINK_RE.finditer(text):
|
||||||
target = local_link_target(path, match.group(1))
|
target = local_link_target(path, match.group(1))
|
||||||
if target is None:
|
if target is None:
|
||||||
continue
|
continue
|
||||||
checked_links += 1
|
checked_links += 1
|
||||||
|
try:
|
||||||
|
target.relative_to(ROOT)
|
||||||
|
except ValueError:
|
||||||
|
errors.append(f"{rel}: link escapes repo -> {match.group(1)}")
|
||||||
|
continue
|
||||||
if not target.exists():
|
if not target.exists():
|
||||||
errors.append(f"{rel}: broken link -> {match.group(1)}")
|
errors.append(f"{rel}: broken link -> {match.group(1)}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user