refactor: move host_db_path/HOST_DB_FILENAME to db_store (#352)
host_db_path is shared DB infrastructure, not supervise-specific, so its canonical home is db_store (alongside DbStore). It resolves bot_bottle_root from supervise_types lazily inside the function — no load-time cycle, and a monkey-patch of supervise_types.bot_bottle_root still propagates. supervise_types re-exports both names for the historical import path (queue_store/audit_store unchanged); the orchestrator registry now imports from db_store. Drops the now-unused `import sys` from supervise_types. Behavior-preserving: full unit suite unchanged (only the pre-existing /bin/sleep sidecar-init errors remain); monkeypatch propagation verified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
+25
-1
@@ -11,6 +11,30 @@ except ImportError:
|
|||||||
from migrations import TableMigrations # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
|
from migrations import TableMigrations # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
|
||||||
|
|
||||||
|
|
||||||
|
# The single shared host state DB. All bot-bottle SQLite stores (supervise
|
||||||
|
# queue, audit, the orchestrator registry) co-tenant this one file — the
|
||||||
|
# TableMigrations schema_key namespaces each store's tables.
|
||||||
|
HOST_DB_FILENAME = "bot-bottle.db"
|
||||||
|
|
||||||
|
|
||||||
|
def host_db_path() -> Path:
|
||||||
|
"""Path to the shared host state DB, `<bot_bottle_root>/db/bot-bottle.db`.
|
||||||
|
|
||||||
|
Kept in its own `db/` subdirectory (not directly under the root) so a
|
||||||
|
backend that can only bind-mount *directories* can share this one file
|
||||||
|
with a sidecar without exposing the root's other contents (git-gate
|
||||||
|
keys, per-bottle state, ...).
|
||||||
|
|
||||||
|
Resolves `bot_bottle_root` from `supervise_types` at call time (a lazy
|
||||||
|
import — avoids a load-time cycle, and lets a monkey-patch of
|
||||||
|
`supervise_types.bot_bottle_root` propagate here)."""
|
||||||
|
try:
|
||||||
|
from . import supervise_types as _st
|
||||||
|
except ImportError: # flat imports inside the sidecar bundle
|
||||||
|
import supervise_types as _st # type: ignore[import-not-found,no-redef] # pylint: disable=import-error,no-name-in-module
|
||||||
|
return _st.bot_bottle_root() / "db" / HOST_DB_FILENAME
|
||||||
|
|
||||||
|
|
||||||
class DbVersionError(Exception):
|
class DbVersionError(Exception):
|
||||||
"""Raised when the on-disk schema is behind the current migration list."""
|
"""Raised when the on-disk schema is behind the current migration list."""
|
||||||
|
|
||||||
@@ -56,4 +80,4 @@ class DbStore:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["DbStore", "DbVersionError"]
|
__all__ = ["DbStore", "DbVersionError", "HOST_DB_FILENAME", "host_db_path"]
|
||||||
|
|||||||
@@ -35,9 +35,8 @@ import time
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from ..db_store import DbStore
|
from ..db_store import DbStore, host_db_path
|
||||||
from ..migrations import TableMigrations
|
from ..migrations import TableMigrations
|
||||||
from ..supervise_types import host_db_path
|
|
||||||
|
|
||||||
# 256 bits of urandom, URL-safe — unguessable per-bottle identity token.
|
# 256 bits of urandom, URL-safe — unguessable per-bottle identity token.
|
||||||
IDENTITY_TOKEN_BYTES = 32
|
IDENTITY_TOKEN_BYTES = 32
|
||||||
|
|||||||
@@ -5,22 +5,28 @@ Proposal, Response, AuditEntry, and host_db_path without creating a
|
|||||||
circular import (supervise imports from queue_store/audit_store and
|
circular import (supervise imports from queue_store/audit_store and
|
||||||
vice-versa).
|
vice-versa).
|
||||||
|
|
||||||
Patching bot_bottle_root on this module propagates through host_db_path
|
host_db_path / HOST_DB_FILENAME now live in db_store (shared DB infra) and
|
||||||
because host_db_path looks up bot_bottle_root via sys.modules[__name__]
|
are re-exported here for the historical import path. db_store.host_db_path
|
||||||
at call time rather than capturing it at import time.
|
resolves bot_bottle_root from this module lazily, so patching
|
||||||
|
supervise_types.bot_bottle_root still propagates to the DB path.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import sys
|
|
||||||
import uuid
|
import uuid
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
# host_db_path / HOST_DB_FILENAME now live in db_store (shared DB infra);
|
||||||
HOST_DB_FILENAME = "bot-bottle.db"
|
# re-exported here for the historical import path. db_store resolves
|
||||||
|
# bot_bottle_root from this module lazily, so patching
|
||||||
|
# supervise_types.bot_bottle_root still propagates.
|
||||||
|
try:
|
||||||
|
from .db_store import HOST_DB_FILENAME, host_db_path
|
||||||
|
except ImportError: # flat imports inside the sidecar bundle
|
||||||
|
from db_store import HOST_DB_FILENAME, host_db_path # type: ignore[import-not-found,no-redef] # pylint: disable=import-error,no-name-in-module
|
||||||
|
|
||||||
TOOL_EGRESS_BLOCK = "egress-block"
|
TOOL_EGRESS_BLOCK = "egress-block"
|
||||||
TOOL_EGRESS_ALLOW = "egress-allow"
|
TOOL_EGRESS_ALLOW = "egress-allow"
|
||||||
@@ -47,19 +53,6 @@ def bot_bottle_root() -> Path:
|
|||||||
return Path.home() / ".bot-bottle"
|
return Path.home() / ".bot-bottle"
|
||||||
|
|
||||||
|
|
||||||
def host_db_path() -> Path:
|
|
||||||
# Look up bot_bottle_root through this module's live namespace so that
|
|
||||||
# monkey-patches on supervise_types.bot_bottle_root take effect.
|
|
||||||
#
|
|
||||||
# Lives in its own "db" subdirectory, not directly under
|
|
||||||
# bot_bottle_root(), so backends that can only bind-mount
|
|
||||||
# directories (macos_container's `container run --mount`, which
|
|
||||||
# rejects file sources with "is not a directory") can share this
|
|
||||||
# one file with a sidecar without also exposing bot_bottle_root()'s
|
|
||||||
# other contents (git-gate keys, per-bottle state, etc.).
|
|
||||||
return sys.modules[__name__].bot_bottle_root() / "db" / HOST_DB_FILENAME
|
|
||||||
|
|
||||||
|
|
||||||
def _require_str(raw: dict[str, object], key: str) -> str:
|
def _require_str(raw: dict[str, object], key: str) -> str:
|
||||||
value = raw.get(key)
|
value = raw.get(key)
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
|
|||||||
Reference in New Issue
Block a user