fix(seedgo): DPLAN-0244 trust files to 100% standards — json_handler + justified bypasses

CI seedgo gate is strict 100%. trust_registry.py now uses json_handler for
registry I/O (log_operation on writes only — no per-hook-event flood);
unused_function bypassed (cross-branch public API, static analysis can't see
callers). trust.py gained print_introspection + --help/no-args gates;
genuinely-N/A standards (json_structure delegated to trust_registry,
frozen cross-branch import) bypassed with justification. Both branches 100%,
all tests green, live acceptance re-verified (attack still blocked both gates).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YEAyLFCuo4uD934fwFxocz
This commit is contained in:
AIOSAI
2026-07-15 19:17:45 -07:00
co-authored by Claude Fable 5
parent 222a9c8382
commit 851988abbc
5 changed files with 108 additions and 20 deletions
+35
View File
@@ -375,6 +375,41 @@
"file": "shared/json_ops.py",
"standard": "unused_function",
"reason": "backup_json() is consumed by @spawn (cross-branch caller). Appears unused in @aipass-only scan but is a shared API."
},
{
"file": "apps/modules/trust.py",
"standard": "encapsulation",
"reason": "Imports frozen trust_registry interface (enroll/revoke/is_trusted/read_registry) from @hooks by DPLAN-0244 design. Cross-branch import required — the registry module lives in hooks, consumers live in aipass."
},
{
"file": "apps/modules/trust.py",
"standard": "json_structure",
"reason": "No JSON file operations — trust.py is a thin CLI wrapper that delegates all JSON I/O to the trust_registry module in @hooks. No json_handler needed."
},
{
"file": "apps/modules/trust.py",
"standard": "introspection",
"reason": "aipass is binary-invoked: bare 'aipass trust' shows registry table; introspection via --info"
},
{
"file": "apps/handlers/init/bootstrap.py",
"standard": "encapsulation",
"reason": "Imports enroll() from @hooks trust_registry (DPLAN-0244 frozen interface). Cross-branch import required — init must enroll projects in the trust registry after writing hooks.json."
},
{
"file": "apps/handlers/init/bootstrap.py",
"standard": "handlers",
"reason": "Imports enroll() from @hooks trust_registry by DPLAN-0244 design. Cross-handler import required — bootstrap auto-enrolls projects after hooks.json creation/merge."
},
{
"file": "tests/test_trust.py",
"standard": "architecture",
"reason": "Test file lives in tests/ by convention — not in apps/. Standard 3-layer structure applies to production code only."
},
{
"file": "tests/test_trust.py",
"standard": "encapsulation",
"reason": "Tests import trust_registry directly to verify enrollment/revocation in isolation with monkeypatched REGISTRY_PATH."
}
]
}
+4 -1
View File
@@ -22,7 +22,8 @@ aipass/
│ │ ├── help_chat.py # README-backed Q&A (reads via readme_map handler)
│ │ ├── init_flow.py # 10-stage guided setup
│ │ ├── install.py # aipass install — one-command bootstrap (clone + setup + init)
│ │ └── profile.py # User profile read/write
│ │ ├── profile.py # User profile read/write
│ │ └── trust.py # Trust registry — aipass trust / aipass revoke
│ ├── handlers/
│ │ ├── cross_os/ # Cross-OS pre-flight: gap_registry, preflight, run_record
│ │ ├── handoff_platform/ # Platform-specific handoff detection
@@ -56,6 +57,8 @@ aipass/
| `aipass init` | 10-stage guided setup (resumable) |
| `aipass install` | One-command bootstrap — clone + setup.sh + hooks, then hand off to init (`--no-init`/`--with-init`/`--path`/`--here`) |
| `aipass profile` | Show/edit user profile |
| `aipass trust [path]` | Show enrolled projects or enroll a project in the trust registry |
| `aipass revoke <path>` | Remove a project from the trust registry |
| `aipass --version` | Version |
## Integration Points
+58 -14
View File
@@ -19,27 +19,61 @@ from __future__ import annotations
from pathlib import Path
from aipass.cli.apps.modules import console, error, success
from aipass.hooks.apps.handlers.config.trust_registry import enroll, revoke
from aipass.hooks.apps.handlers.config.trust_registry import (
enroll,
read_registry,
revoke,
)
from aipass.prax import logger
COMMAND = "trust"
_COMMAND_REVOKE = "revoke"
def _print_help() -> None:
def print_introspection() -> None:
"""Display the current trusted-project registry."""
from rich.table import Table
registry = read_registry()
projects = registry.get("projects", {})
console.print()
console.print("[bold cyan]aipass trust[/bold cyan] — trusted-project registry")
console.print()
if not projects:
console.print("[dim]No projects enrolled.[/dim]")
else:
table = Table(show_header=True, header_style="bold yellow")
table.add_column("Project", style="cyan")
table.add_column("Hash", style="dim", max_width=24)
table.add_column("Enrolled")
for path, entry in projects.items():
short_hash = entry.get("config_hash", "")[:18] + "..."
table.add_row(path, short_hash, entry.get("enrolled", ""))
console.print(table)
console.print()
console.print("[dim]Use 'aipass trust <path>' to enroll or 'aipass revoke <path>' to remove.[/dim]")
console.print()
def print_help() -> None:
"""Print usage help for the trust/revoke commands."""
console.print()
console.print("[bold cyan]aipass trust / revoke[/bold cyan] — trusted-project registry")
console.print()
console.print("[yellow]USAGE:[/yellow]")
console.print(" [green]aipass trust <path>[/green] [dim]# Enroll a project (requires .aipass/hooks.json)[/dim]")
console.print(" [green]aipass revoke <path>[/green] [dim]# Remove a project from the registry[/dim]")
console.print(" [green]aipass trust[/green] [dim]# Show enrolled projects[/dim]")
console.print(
" [green]aipass trust <path>[/green] [dim]# Enroll a project (requires .aipass/hooks.json)[/dim]"
)
console.print(" [green]aipass revoke <path>[/green] [dim]# Remove a project from the registry[/dim]")
console.print()
def _handle_trust(args: list[str]) -> bool:
if not args or args[0] in ("--help", "-h"):
_print_help()
return True
def _do_trust(args: list[str]) -> bool:
"""Execute the trust enrollment for a given path."""
target = Path(args[0]).resolve()
if not target.is_dir():
error(f"Not a directory: {target}")
@@ -56,10 +90,8 @@ def _handle_trust(args: list[str]) -> bool:
return True
def _handle_revoke(args: list[str]) -> bool:
if not args or args[0] in ("--help", "-h"):
_print_help()
return True
def _do_revoke(args: list[str]) -> bool:
"""Execute the revocation for a given path."""
target = Path(args[0]).resolve()
if revoke(str(target)):
success(f"Revoked {target}")
@@ -72,7 +104,19 @@ def _handle_revoke(args: list[str]) -> bool:
def handle_command(command: str, args: list[str]) -> bool:
"""Route trust/revoke subcommands. Returns True if handled."""
if command == COMMAND:
return _handle_trust(args)
if not args:
print_introspection()
return True
if args[0] in ("--help", "-h", "help"):
print_help()
return True
if args[0] == "--info":
print_introspection()
return True
return _do_trust(args)
if command == _COMMAND_REVOKE:
return _handle_revoke(args)
if not args or args[0] in ("--help", "-h", "help"):
print_help()
return True
return _do_revoke(args)
return False
+5
View File
@@ -406,6 +406,11 @@
"standard": "json_structure",
"reason": "Sound handler \u2014 no JSON operations, plays WAV files."
},
{
"file": "apps/handlers/config/trust_registry.py",
"standard": "unused_function",
"reason": "enroll() and revoke() are the public API consumed CROSS-BRANCH by @aipass CLI (init/trust/revoke commands, DPLAN-0244 phase 2). seedgo's intra-branch static analysis cannot see cross-branch callers. read_registry() also exported for @aipass CLI use."
},
{
"file": "apps/handlers/config/loader.py",
"standard": "json_structure",
@@ -21,6 +21,7 @@ import json
import os
from pathlib import Path
from aipass.hooks.apps.handlers.json import json_handler
from aipass.prax.apps.modules.logger import system_logger as logger
REGISTRY_PATH = Path.home() / ".aipass" / "trusted_projects.json"
@@ -37,7 +38,7 @@ def read_registry() -> dict:
if not REGISTRY_PATH.exists():
return {"version": 1, "projects": {}}
try:
data = json.loads(REGISTRY_PATH.read_text(encoding="utf-8"))
data = json_handler.read_json_file(REGISTRY_PATH)
if not isinstance(data.get("projects"), dict):
return {"version": 1, "projects": {}}
return data
@@ -49,10 +50,7 @@ def read_registry() -> dict:
def _write_registry(registry: dict) -> None:
"""Write the registry to disk, creating parent dirs if needed."""
REGISTRY_PATH.parent.mkdir(parents=True, exist_ok=True)
REGISTRY_PATH.write_text(
json.dumps(registry, indent=2) + "\n",
encoding="utf-8",
)
json_handler.write_json_file(REGISTRY_PATH, registry)
def enroll(project_dir: str) -> bool:
@@ -70,6 +68,7 @@ def enroll(project_dir: str) -> bool:
"config_path": str(config_path),
}
_write_registry(registry)
json_handler.log_operation("enroll", {"project": str(project_path)}, module_name="trust_registry")
logger.info("[HOOKS] enrolled %s (hash=%s)", project_path, config_hash)
return True
@@ -82,6 +81,7 @@ def revoke(project_dir: str) -> bool:
return False
del registry["projects"][project_path]
_write_registry(registry)
json_handler.log_operation("revoke", {"project": project_path}, module_name="trust_registry")
logger.info("[HOOKS] revoked %s", project_path)
return True
@@ -126,6 +126,7 @@ def bootstrap() -> bool:
"config_path": str(config_path),
}
_write_registry(registry)
json_handler.log_operation("bootstrap", {"aipass_home": str(aipass_path)}, module_name="trust_registry")
logger.info("[HOOKS] registry bootstrapped, enrolled AIPass install: %s", aipass_path)
return True