Files
AIPass/src/commons/apps/handlers/__init__.py
T
18acb30f83 chore(system): session 34 — maintenance + multi-branch work (#70)
* fix(ai_mail): resolve relative mailbox_path bug + archive dead handlers

Fix get_user_by_email() and get_all_users() returning relative mailbox_path
values from registry instead of absolute paths (causing doubled paths in reply).
Added path resolution matching get_current_user() pattern.

Archive 7 unused handler files to apps/.archive/ (gitignored):
- pending_work.py — planned feature, never wired
- lock_utils.py — superseded by inbox_lock.py
- data_ops.py — consumer (error_monitor) was archived
- config_generator.py, users/load.py, registry/validate.py — scaffolded, never used
- trigger/error_handler.py — superseded by trigger branch's event system

Added test_user_paths.py (13 tests) covering absolute path resolution.

Co-Authored-By: @ai_mail <ai_mail@aipass>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(spawn): seedgo compliance cleanup — 93% to 98%

Archive legacy files (dev.local.md, ai_mail.local/, .seed/). Update META
Modified dates on 22 files. Update README architecture tree and freshness.
Fix 15 Pyright unused warnings. Add introspection no-args gates to 6
modules. Wire json_handler + log_operation to 15 operational files. Add
seedgo bypass for 5 pure data files and log_structure. Remove deprecated
dev.local.md from builder template.

Co-Authored-By: @spawn <spawn@aipass>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(system): session 34 — maintenance day, multi-branch work

System changes:
- setup.sh: symlink install replaces .bashrc PATH export for drone/seedgo
- .claude/settings.json: deny list moved to per-branch settings.local.json
- .gitignore: updated
- CLAUDE.md culture doc: stale refs fixed (Cortex→spawn, id.json→passport.json)

Branch work (accumulated from 15-branch rounds):
- daemon: stale term cleanup, plugin removals, json handler modernization
- drone: module refactor (discovery, registry, router, resolver, config)
- commons: 50+ file cleanup (imports, handlers, modules)
- flow: template loader, plan type system, command parser

Per-branch settings.local.json: reworked deny lists — allow PR workflow,
deny destructive git ops (reset, rebase, merge, clean, force push, rm -rf).
Fixed pattern syntax from :* to * glob.

Co-Authored-By: @devpulse <devpulse@aipass>

---------

Co-authored-by: @ai_mail <ai_mail@aipass>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: @spawn <spawn@aipass>
Co-authored-by: @devpulse <devpulse@aipass>
2026-03-17 16:45:05 -07:00

108 lines
3.5 KiB
Python

# ===================AIPASS====================
# META DATA HEADER
# Name: __init__.py - The Commons handlers package
# Date: 2026-03-07
# Version: 2.0.0
# Category: commons/apps/handlers
# =============================================
"""Commons handlers package - Security protected."""
import inspect
from pathlib import Path
MY_BRANCH = "commons" # Commons is standalone, not under aipass.*
def _find_real_caller():
"""Walk the stack to find the actual file that triggered this import."""
stack = inspect.stack()
this_file = str(Path(__file__).resolve())
for frame_info in stack:
filename = frame_info.filename
if this_file in str(Path(filename).resolve()):
continue
if filename.startswith("<") or "importlib" in filename:
continue
import_line = None
if frame_info.code_context:
import_line = frame_info.code_context[0].strip()
return str(Path(filename).resolve()), import_line
return None, None
def _extract_branch_name(filepath: str) -> str:
"""Extract branch name from a file path."""
parts = Path(filepath).parts
for i, part in enumerate(parts):
if part == "aipass":
if i + 1 < len(parts):
return parts[i + 1]
# Check for commons specifically
for i, part in enumerate(parts):
if part == "commons":
return "commons"
return "unknown"
def _guard_branch_access():
"""Block cross-branch handler imports."""
caller_file, import_line = _find_real_caller()
import os
if os.environ.get("AIPASS_DEBUG_GUARD"):
import sys
print(f"[GUARD DEBUG] caller_file = {caller_file}", file=sys.stderr)
print(f"[GUARD DEBUG] import_line = {import_line}", file=sys.stderr)
if caller_file is None:
stack = inspect.stack()
for frame in stack:
if frame.filename in ("<string>", "<stdin>"):
target_line = "unknown"
if frame.code_context:
target_line = frame.code_context[0].strip()
raise ImportError(
f"\n{'='*60}\n"
f"ACCESS DENIED: Cross-branch handler import blocked\n"
f"{'='*60}\n"
f" Caller: interactive/script\n"
f" Blocked: {target_line}\n"
f"\n"
f" Handlers are internal to their branch.\n"
f" Use the module API instead:\n"
f" from {MY_BRANCH}.apps.modules.<module> import <function>\n"
f"{'='*60}"
)
return
# IMPORTANT: Commons is at src/commons/, not src/aipass/commons/
# Check if caller is from within the commons directory
if "/commons/" in caller_file:
return # Same branch, allowed
caller_branch = _extract_branch_name(caller_file)
caller_filename = Path(caller_file).name
blocked_import = import_line if import_line else "unknown"
raise ImportError(
f"\n{'='*60}\n"
f"ACCESS DENIED: Cross-branch handler import blocked\n"
f"{'='*60}\n"
f" Caller branch: {caller_branch}\n"
f" Caller file: {caller_filename}\n"
f" Blocked: {blocked_import}\n"
f"\n"
f" Handlers are internal to their branch.\n"
f" Use the module API instead:\n"
f" from {MY_BRANCH}.apps.modules.<module> import <function>\n"
f"{'='*60}"
)
# Run guard at import time
_guard_branch_access()