@miller-tech/uap 2.16.7 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/capacity-policy.json +33 -0
- package/config/model-profiles/qwen38.json +32 -33
- package/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +57 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/capacity/policy.d.ts +32 -1
- package/dist/capacity/policy.d.ts.map +1 -1
- package/dist/capacity/policy.js +123 -4
- package/dist/capacity/policy.js.map +1 -1
- package/dist/capacity/probe.d.ts +26 -0
- package/dist/capacity/probe.d.ts.map +1 -1
- package/dist/capacity/probe.js +84 -3
- package/dist/capacity/probe.js.map +1 -1
- package/dist/cli/inference.d.ts +4 -0
- package/dist/cli/inference.d.ts.map +1 -1
- package/dist/cli/inference.js +74 -8
- package/dist/cli/inference.js.map +1 -1
- package/dist/cli/merge-gate.d.ts +59 -0
- package/dist/cli/merge-gate.d.ts.map +1 -0
- package/dist/cli/merge-gate.js +238 -0
- package/dist/cli/merge-gate.js.map +1 -0
- package/dist/cli/merge-queue.d.ts +13 -0
- package/dist/cli/merge-queue.d.ts.map +1 -1
- package/dist/cli/merge-queue.js +48 -2
- package/dist/cli/merge-queue.js.map +1 -1
- package/dist/cli/mission.d.ts +25 -0
- package/dist/cli/mission.d.ts.map +1 -0
- package/dist/cli/mission.js +225 -0
- package/dist/cli/mission.js.map +1 -0
- package/dist/cli/orch.d.ts +27 -0
- package/dist/cli/orch.d.ts.map +1 -0
- package/dist/cli/orch.js +70 -0
- package/dist/cli/orch.js.map +1 -0
- package/dist/cli/systemd-services.d.ts.map +1 -1
- package/dist/cli/systemd-services.js +44 -0
- package/dist/cli/systemd-services.js.map +1 -1
- package/dist/delivery/merge-gate.d.ts +168 -0
- package/dist/delivery/merge-gate.d.ts.map +1 -0
- package/dist/delivery/merge-gate.js +309 -0
- package/dist/delivery/merge-gate.js.map +1 -0
- package/dist/inference/analysis.d.ts +69 -3
- package/dist/inference/analysis.d.ts.map +1 -1
- package/dist/inference/analysis.js +123 -7
- package/dist/inference/analysis.js.map +1 -1
- package/dist/inference/probe.d.ts +38 -1
- package/dist/inference/probe.d.ts.map +1 -1
- package/dist/inference/probe.js +303 -30
- package/dist/inference/probe.js.map +1 -1
- package/dist/inference/strata.d.ts +95 -0
- package/dist/inference/strata.d.ts.map +1 -0
- package/dist/inference/strata.js +167 -0
- package/dist/inference/strata.js.map +1 -0
- package/dist/mission/database.d.ts +29 -0
- package/dist/mission/database.d.ts.map +1 -0
- package/dist/mission/database.js +131 -0
- package/dist/mission/database.js.map +1 -0
- package/dist/mission/ledger.d.ts +109 -0
- package/dist/mission/ledger.d.ts.map +1 -0
- package/dist/mission/ledger.js +294 -0
- package/dist/mission/ledger.js.map +1 -0
- package/dist/mission/poll-cycle.d.ts +73 -0
- package/dist/mission/poll-cycle.d.ts.map +1 -0
- package/dist/mission/poll-cycle.js +100 -0
- package/dist/mission/poll-cycle.js.map +1 -0
- package/dist/mission/poll-executor.d.ts +91 -0
- package/dist/mission/poll-executor.d.ts.map +1 -0
- package/dist/mission/poll-executor.js +328 -0
- package/dist/mission/poll-executor.js.map +1 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +33 -27
- package/dist/models/types.js.map +1 -1
- package/dist/self-tuning/profiles/qwen38.d.ts +13 -14
- package/dist/self-tuning/profiles/qwen38.d.ts.map +1 -1
- package/dist/self-tuning/profiles/qwen38.js +17 -18
- package/dist/self-tuning/profiles/qwen38.js.map +1 -1
- package/dist/types/mission.d.ts +80 -0
- package/dist/types/mission.d.ts.map +1 -0
- package/dist/types/mission.js +12 -0
- package/dist/types/mission.js.map +1 -0
- package/docs/architecture/adr/0003-mission-orchestrator.md +99 -0
- package/docs/architecture/adr/0004-deterministic-merge-gate.md +127 -0
- package/docs/architecture/adr/0005-ollama-compatible-surface.md +74 -0
- package/docs/guides/CAPACITY_POLICY.md +49 -0
- package/docs/guides/INFERENCE_HEALTH.md +65 -8
- package/docs/guides/MISSIONS.md +170 -0
- package/docs/guides/PROXY.md +50 -0
- package/docs/reports/2026-10-02-plane-admin-fail-closed.md +70 -0
- package/docs/reports/2026-10-02-plane-admin-protect-session.md +116 -0
- package/docs/visual/merge-gate.html +404 -0
- package/docs/visual/mission-orchestrator.html +472 -0
- package/package.json +2 -2
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/expert_review_required.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
- package/src/policies/enforcers/plane_admin_protect.py +133 -0
- package/src/policies/schemas/policies/plane-admin-protect.md +55 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/templates/hooks/uap-policy-gate.sh +33 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +1271 -89
- package/tools/agents/scripts/requirements-proxy.txt +1 -1
- package/tools/agents/tests/test_anthropic_proxy_streaming.py +171 -0
- package/tools/agents/tests/test_gate_failclosed_plane_admin.py +248 -0
- package/tools/agents/tests/test_ollama_compat.py +320 -0
- package/tools/agents/tests/test_plane_admin_protect.py +124 -0
- package/tools/agents/tests/test_stream_heartbeat.py +77 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""plane-admin-protect enforcer: agents must not reset/override the Plane admin
|
|
3
|
+
account credentials unless the owner explicitly approved via a waiver file.
|
|
4
|
+
|
|
5
|
+
Observed (2026-09-24 and 2026-09-30): agents independently ran
|
|
6
|
+
`docker exec plane-app-api-1 python manage.py ... set_password admin@pay2u.com.au`
|
|
7
|
+
and overwrote the owner's password TWICE. The owner had to ask for a reset.
|
|
8
|
+
UAP memory stores a PROTECT note; this enforcer makes that note mechanical.
|
|
9
|
+
|
|
10
|
+
Scope (Bash/bash/run_bash/shell operations only):
|
|
11
|
+
- Any shell command that targets the Plane stack (plane-app-api-1, plane-app,
|
|
12
|
+
134.199.173.65, /opt/plane, plane-db) AND performs a credential mutation
|
|
13
|
+
(reset_password / set_password / changepassword / createsuperuser / passwd)
|
|
14
|
+
is refused.
|
|
15
|
+
|
|
16
|
+
Escape hatch (owner approval, mirrors the policies/waivers convention used by
|
|
17
|
+
the expert-review gate): write `policies/waivers/plane-admin-reset` containing
|
|
18
|
+
a line `expires: YYYY-MM-DD` (today or later), then retry. The waiver is a
|
|
19
|
+
file the OWNER writes; an agent writing it without an explicit owner request
|
|
20
|
+
in the current session violates the policy even though the gate would pass.
|
|
21
|
+
|
|
22
|
+
Known limits. This is a text gate over a language with unbounded ways to say
|
|
23
|
+
the same thing. It scans the command with `scannable_command()`, which strips
|
|
24
|
+
heredoc bodies and multi-word quoted blobs so a command that merely NAMES a
|
|
25
|
+
credential verb in prose (a commit message, a `uap memory store`, a script fed
|
|
26
|
+
over a heredoc) is not refused. The observed incident — `docker exec ...
|
|
27
|
+
changepassword ...` — is caught because `exec` hands text to a shell, so
|
|
28
|
+
`scannable_command` leaves that payload intact. A mutation quoted inside a
|
|
29
|
+
plain `ssh host "..."` with no shell-exec token, or routed through `eval`/
|
|
30
|
+
base64, evades every text rule by construction. Treat this as raising the cost,
|
|
31
|
+
not as a boundary.
|
|
32
|
+
"""
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import re
|
|
36
|
+
import sys
|
|
37
|
+
from datetime import date
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
|
|
40
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
41
|
+
from _common import emit, parse_cli, repo_root, scannable_command # noqa: E402
|
|
42
|
+
|
|
43
|
+
WAIVER_PATH = "policies/waivers/plane-admin-reset"
|
|
44
|
+
|
|
45
|
+
SHELL_OPS = {"bash", "run_bash", "shell", "execute_command", "terminal"}
|
|
46
|
+
|
|
47
|
+
# Substring match, so `plane-app` already covers plane-app-api-1/-worker/-beat;
|
|
48
|
+
# the specific spellings are listed for documentation, not because they match
|
|
49
|
+
# anything the generic one would not.
|
|
50
|
+
TARGETS = (
|
|
51
|
+
"plane-app",
|
|
52
|
+
"134.199.173.65",
|
|
53
|
+
"/opt/plane",
|
|
54
|
+
"plane-db",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
MUTATIONS = (
|
|
58
|
+
"reset_password",
|
|
59
|
+
"set_password",
|
|
60
|
+
"changepassword",
|
|
61
|
+
"createsuperuser",
|
|
62
|
+
"passwd",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _waiver_expiry(waiver: Path) -> tuple[bool, str]:
|
|
67
|
+
"""(valid, detail) for a waiver file that exists.
|
|
68
|
+
|
|
69
|
+
A waiver is only honoured when it parses an `expires: YYYY-MM-DD` line that
|
|
70
|
+
is today or later. An unreadable file is NOT treated as absent — the gate
|
|
71
|
+
fails closed rather than crashing, so a permission problem cannot be used to
|
|
72
|
+
slip past it (or to mask it as an internal error).
|
|
73
|
+
"""
|
|
74
|
+
try:
|
|
75
|
+
text = waiver.read_text()
|
|
76
|
+
except OSError as e:
|
|
77
|
+
return False, f"waiver file exists but could not be read ({e.strerror or e})"
|
|
78
|
+
m = re.search(r"expires:\s*(\d{4}-\d{2}-\d{2})", text)
|
|
79
|
+
if not m:
|
|
80
|
+
return False, "waiver file is missing an 'expires: YYYY-MM-DD' line"
|
|
81
|
+
try:
|
|
82
|
+
expires = date.fromisoformat(m.group(1))
|
|
83
|
+
except ValueError:
|
|
84
|
+
return False, f"waiver 'expires: {m.group(1)}' is not a valid date"
|
|
85
|
+
if expires >= date.today():
|
|
86
|
+
return True, f"owner waiver valid until {m.group(1)}"
|
|
87
|
+
return False, f"waiver expired on {m.group(1)}"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def main() -> None:
|
|
91
|
+
operation, args = parse_cli()
|
|
92
|
+
if operation.lower() not in SHELL_OPS:
|
|
93
|
+
emit(True, "plane-admin-protect: not a shell operation")
|
|
94
|
+
|
|
95
|
+
raw = str(args.get("command") or "")
|
|
96
|
+
if not raw:
|
|
97
|
+
emit(True, "plane-admin-protect: no command payload")
|
|
98
|
+
cmd = scannable_command(raw).lower()
|
|
99
|
+
|
|
100
|
+
if not any(t in cmd for t in TARGETS):
|
|
101
|
+
emit(True, "plane-admin-protect: command does not target the Plane stack")
|
|
102
|
+
|
|
103
|
+
verb = next((v for v in MUTATIONS if v in cmd), None)
|
|
104
|
+
if verb is None:
|
|
105
|
+
emit(True, "plane-admin-protect: no credential mutation verb")
|
|
106
|
+
|
|
107
|
+
waiver = repo_root() / WAIVER_PATH
|
|
108
|
+
if waiver.exists():
|
|
109
|
+
valid, detail = _waiver_expiry(waiver)
|
|
110
|
+
if valid:
|
|
111
|
+
emit(True, f"plane-admin-protect: {detail}")
|
|
112
|
+
emit(
|
|
113
|
+
False,
|
|
114
|
+
f"plane-admin-protect: {detail} — refresh it with the owner's approval.",
|
|
115
|
+
route="owner-waiver",
|
|
116
|
+
waiverHint=f"owner writes {WAIVER_PATH} with a line 'expires: YYYY-MM-DD'",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
emit(
|
|
120
|
+
False,
|
|
121
|
+
"plane-admin-protect: refusing credential mutation on the Plane stack "
|
|
122
|
+
f"(matched target + verb {verb!r}). The Plane admin account "
|
|
123
|
+
"admin@pay2u.com.au (droplet 134.199.173.65, /opt/plane/plane-app) must "
|
|
124
|
+
"NOT be reset/overridden unless the owner explicitly asks. Owner "
|
|
125
|
+
"approval: write policies/waivers/plane-admin-reset with a line "
|
|
126
|
+
"'expires: YYYY-MM-DD' and retry.",
|
|
127
|
+
route="owner-waiver",
|
|
128
|
+
waiverHint=f"owner writes {WAIVER_PATH} with a line 'expires: YYYY-MM-DD'",
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
main()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# plane-admin-protect
|
|
2
|
+
|
|
3
|
+
**Category**: safety
|
|
4
|
+
**Level**: REQUIRED
|
|
5
|
+
**Enforcement Stage**: pre-exec
|
|
6
|
+
**Default**: on
|
|
7
|
+
**Tags**: plane, credentials, admin, safety, droplet, owner-waiver
|
|
8
|
+
|
|
9
|
+
## Rule
|
|
10
|
+
|
|
11
|
+
A `Bash`/`run_bash`/`shell` command that **both** targets the Plane stack **and**
|
|
12
|
+
performs a credential mutation is blocked:
|
|
13
|
+
|
|
14
|
+
- Targets (substring match): `plane-app` (covers `plane-app-api-1`/`-worker`/`-beat`),
|
|
15
|
+
`134.199.173.65`, `/opt/plane`, `plane-db`.
|
|
16
|
+
- Mutation verbs: `reset_password`, `set_password`, `changepassword`,
|
|
17
|
+
`createsuperuser`, `passwd`.
|
|
18
|
+
|
|
19
|
+
The Plane admin account `admin@pay2u.com.au` (droplet `134.199.173.65`,
|
|
20
|
+
`/opt/plane/plane-app`) must **not** be reset or overridden unless the owner
|
|
21
|
+
explicitly asks for it in the current session.
|
|
22
|
+
|
|
23
|
+
**Allowed**: read-only Plane commands (`kubectl logs plane-app-worker`,
|
|
24
|
+
`docker exec plane-app-api-1 python manage.py showmigrations`, …) and any command
|
|
25
|
+
that merely *names* a credential verb in prose — a commit message, a
|
|
26
|
+
`uap memory store`, a script fed over a heredoc. The scan uses
|
|
27
|
+
`scannable_command()`, which strips heredoc bodies and multi-word quoted blobs,
|
|
28
|
+
so prose that mentions the verbs is not refused.
|
|
29
|
+
|
|
30
|
+
**Escape hatch (owner approval).** Write `policies/waivers/plane-admin-reset`
|
|
31
|
+
containing a line `expires: YYYY-MM-DD` (today or later), then retry. The waiver
|
|
32
|
+
is a file the OWNER writes; an agent writing it without an explicit owner request
|
|
33
|
+
in the current session violates the policy even though the gate would pass. A
|
|
34
|
+
waiver that is expired, missing its `expires:` line, or unreadable fails the gate
|
|
35
|
+
closed (refused), never allowed and never a crash.
|
|
36
|
+
|
|
37
|
+
**Known limits.** This is a text gate over a language with unbounded ways to say
|
|
38
|
+
the same thing. A mutation quoted inside a plain `ssh host "..."` with no
|
|
39
|
+
shell-exec token, or routed through `eval`/base64, evades every text rule by
|
|
40
|
+
construction. Treat this as raising the cost, not as a boundary.
|
|
41
|
+
|
|
42
|
+
## Why
|
|
43
|
+
|
|
44
|
+
Observed live (2026-09-24 and 2026-09-30): agents independently ran
|
|
45
|
+
`docker exec plane-app-api-1 python manage.py ... set_password admin@pay2u.com.au`
|
|
46
|
+
and overwrote the owner's password TWICE. The owner had to ask for a reset. UAP
|
|
47
|
+
memory stores a PROTECT note; this enforcer makes that note mechanical rather
|
|
48
|
+
than a reminder an agent can forget or route around.
|
|
49
|
+
|
|
50
|
+
## Enforcement
|
|
51
|
+
|
|
52
|
+
Python enforcer `plane_admin_protect.py` (Bash/run_bash/shell ops only). Emits a
|
|
53
|
+
specific remediation: the refusal names the matched target and verb and points at
|
|
54
|
+
the owner-waiver path. Install with `uap policy install plane-admin-protect`,
|
|
55
|
+
which auto-attaches the enforcer from `src/policies/enforcers/plane_admin_protect.py`.
|
|
Binary file
|
|
@@ -399,6 +399,9 @@ fail_closed() {
|
|
|
399
399
|
schema_diff_gate)
|
|
400
400
|
echo "[UAP policy gate] FAIL-CLOSED: this commit touches watched schema paths but the schema-diff enforcer could not run (${why}). Blocked so a broken/absent gate can't become a bypass. Restore it with: uap policy verify --repair (or uap policy install schema-diff-gate if the manifest is gone; npm run build if dist/ is missing). Operator override: UAP_SELF_PROTECT_OFF=1 in the environment." >&2
|
|
401
401
|
;;
|
|
402
|
+
plane_admin_protect)
|
|
403
|
+
echo "[UAP policy gate] FAIL-CLOSED: this shell command can mutate the plane-admin control surface but the plane_admin_protect enforcer could not run (${why}). Blocked so a broken/absent gate can't become a bypass. Restore it with: uap policy verify --repair (or uap policy install plane-admin-protect if the manifest is gone). Operator override: UAP_SELF_PROTECT_OFF=1 in the environment." >&2
|
|
404
|
+
;;
|
|
402
405
|
*)
|
|
403
406
|
echo "[UAP policy gate] FAIL-CLOSED: this operation touches the enforcement control surface but the self-protect enforcer could not run (${why}). Blocked so a broken/absent gate can't become a bypass. (Operator override: UAP_SELF_PROTECT_OFF=1.)" >&2
|
|
404
407
|
;;
|
|
@@ -524,13 +527,43 @@ print("1" if (inv and not inert) else "0")
|
|
|
524
527
|
# refused every commit and push in the session with no working remedy.
|
|
525
528
|
[[ "${UAP_SELF_PROTECT_OFF:-}" == "1" ]] && COMMIT_OP=0
|
|
526
529
|
|
|
530
|
+
# Is this a SHELL-EXECUTION tool call? plane_admin_protect guards the plane-admin
|
|
531
|
+
# control surface (policy registration, the plane-admin rows the gate reads out of
|
|
532
|
+
# policies.db, the .policy-tools/ enforcer copies), and that surface is reachable
|
|
533
|
+
# almost exclusively through the shell: `uap policy install/verify`, `sqlite3
|
|
534
|
+
# agents/data/memory/policies.db ...`, `rm -rf .policy-tools/...`. An Edit/Write
|
|
535
|
+
# of an ordinary source file never invokes it, so arming the fail-closed net there
|
|
536
|
+
# would turn a broken plane-admin enforcer into a blanket block on every edit in
|
|
537
|
+
# the session -- the same over-reach the COMMIT_OP scoping exists to avoid for
|
|
538
|
+
# schema_diff_gate. Keyed on the TOOL name rather than command text because the
|
|
539
|
+
# enforcer's own activation test is tool-based: a shell tool is the only one it is
|
|
540
|
+
# ever asked about.
|
|
541
|
+
SHELL_OP=0
|
|
542
|
+
case " $TOOL " in
|
|
543
|
+
*" Bash "*|*" bash "*|*" run_bash "*|*" BashTool "*|*" Shell "*|*" shell "*|*" Terminal "*|*" terminal "*|*" execute_command "*|*" run_command "*|*" exec "*|*" local_shell "*|*" command "*)
|
|
544
|
+
SHELL_OP=1
|
|
545
|
+
;;
|
|
546
|
+
esac
|
|
547
|
+
# Same operator hatch as SEC_SENSITIVE/COMMIT_OP: UAP_SELF_PROTECT_OFF is
|
|
548
|
+
# documented as clearing the whole fail-closed net, so it has to clear this arm
|
|
549
|
+
# too -- otherwise the override named in the refusal is a no-op for exactly the
|
|
550
|
+
# case that prints it.
|
|
551
|
+
[[ "${UAP_SELF_PROTECT_OFF:-}" == "1" ]] && SHELL_OP=0
|
|
552
|
+
|
|
527
553
|
# Which enforcers must fail CLOSED, and when. Called from `if`, never as the
|
|
528
554
|
# left side of `&&`: this script runs under `set -e`, and `if` suspends it for
|
|
529
555
|
# the whole condition.
|
|
556
|
+
#
|
|
557
|
+
# plane_admin_protect arms ONLY for shell-execution tools (SHELL_OP): its guarded
|
|
558
|
+
# surface is mutable through the shell and nothing else, so a missing or errored
|
|
559
|
+
# plane-admin enforcer on a Bash call is a live bypass of the admin controls,
|
|
560
|
+
# while the same broken enforcer on an Edit is unrelated to that surface and must
|
|
561
|
+
# keep failing open (the gate is fail-soft by design for what it is not guarding).
|
|
530
562
|
must_fail_closed() {
|
|
531
563
|
case "$1" in
|
|
532
564
|
enforcement_self_protect) [[ "$SEC_SENSITIVE" == "1" ]] ;;
|
|
533
565
|
schema_diff_gate) [[ "$COMMIT_OP" == "1" ]] ;;
|
|
566
|
+
plane_admin_protect) [[ "$SHELL_OP" == "1" ]] ;;
|
|
534
567
|
*) false ;;
|
|
535
568
|
esac
|
|
536
569
|
}
|