rename(547): the server is grimoire — package, image, DB defaults, backups
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 56s
CI & Build / integration (push) Successful in 1m4s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 44s

Step 2 of the Scribe -> Grimoire rename.

- src/scribe -> src/grimoire, and every import, patch target, module path,
  hypercorn entry point and `python -m grimoire.restore` with it; pyproject,
  uv.lock and the frontend package are named grimoire.
- Image git.fabledsword.com/bvandeusen/fabledgrimoire; CI's Postgres service
  runs as grimoire / grimoire_test.
- Compose files default the DB user, database and (prod) volume to grimoire,
  each overridable from .env, so an install created as Scribe keeps its data
  by setting POSTGRES_USER, POSTGRES_DB and PGDATA_VOLUME.
- Backups are written as grimoire-<ts>.tar with format grimoire-backup-tar.
  Archives named scribe-* with the scribe-backup-tar manifest still restore
  and are still counted at the destination (folder and S3), with tests.
- Exports, the MCP auth realm, the ASGI scope key and the persistent logger
  carry the new name.

Kept on purpose: the secret-sealing key label stays "scribe.secrets.v1",
because every stored secret was derived under it.

Plugin identity (plugin name, hooks, env vars, .scribe marker, skills) is
step 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-22 10:50:45 -04:00
co-authored by Claude Opus 5.5
parent e99f1169f7
commit 0f5ef0be63
447 changed files with 3611 additions and 3558 deletions
+10 -10
View File
@@ -18,7 +18,7 @@ import base64
import httpx
import pytest
from scribe.services.forge import (
from grimoire.services.forge import (
ForgeError,
ForgeNotFound,
ForgeSelector,
@@ -168,7 +168,7 @@ def test_full_values_build_a_gitea_adapter():
def test_full_values_build_a_github_adapter():
from scribe.services.forge import GitHubForge
from grimoire.services.forge import GitHubForge
assert isinstance(
build_adapter("github", "https://github.com", "tok"), GitHubForge
@@ -205,7 +205,7 @@ def test_forge_error_taxonomy_is_catchable_as_one_family():
def test_adapter_contract_surface():
"""Both adapters implement exactly this surface — the second
implementation is what proves it's a contract."""
from scribe.services.forge import FORGE_KINDS, GitHubForge
from grimoire.services.forge import FORGE_KINDS, GitHubForge
for cls in (GiteaForge, GitHubForge):
for method in (
@@ -223,8 +223,8 @@ def test_forge_routes_registered_at_their_post_2778_homes():
The old instance-wide /api/admin/forge endpoints must be GONE, not
coexisting — a legacy config surface that still wrote admin settings
would silently configure nothing (one path, not two)."""
from scribe.app import create_app
from scribe.routes import admin as admin_routes
from grimoire.app import create_app
from grimoire.routes import admin as admin_routes
for name in ("get_forge_webhook_settings", "update_forge_webhook_settings"):
assert callable(getattr(admin_routes, name))
@@ -243,7 +243,7 @@ def test_settings_kv_surface_masks_the_webhook_secret():
endpoints' masking is bypassable by reading the raw KV rows. The forge
token lives on keyring rows, not in the KV, so it is deliberately not a
secret KEY here."""
from scribe.routes.settings import _SECRET_KEYS, _masked
from grimoire.routes.settings import _SECRET_KEYS, _masked
out = _masked({"forge_webhook_secret": "sec", "smtp_password": "pw", "theme": "dark"})
assert out["forge_webhook_secret"] == "********"
@@ -258,13 +258,13 @@ def test_settings_kv_surface_masks_the_webhook_secret():
def test_connection_to_dict_never_carries_the_token():
"""The model is the last line: every list/create/update route returns
to_dict(), so a field added here is a field leaked there."""
from scribe.models.forge_connection import ForgeConnection
from grimoire.models.forge_connection import ForgeConnection
assert "token" not in ForgeConnection.to_dict.__code__.co_consts
def test_config_has_the_docker_secret_channel():
from scribe.config import Config
from grimoire.config import Config
for attr in ("FORGE_KIND", "FORGE_BASE_URL", "FORGE_TOKEN"):
assert hasattr(Config, attr)
@@ -275,13 +275,13 @@ def test_config_has_the_docker_secret_channel():
# Bearer auth, the missing last_commit_sha, the codeload redirect.
def _github(handler, base: str = "https://github.com"):
from scribe.services.forge import GitHubForge
from grimoire.services.forge import GitHubForge
return GitHubForge(base, "gh-tok", transport=httpx.MockTransport(handler))
def test_github_resolve_repo_is_the_same_host_join():
from scribe.services.forge import GitHubForge
from grimoire.services.forge import GitHubForge
forge = GitHubForge("https://github.com", "t")
assert forge.resolve_repo("git@github.com:alice/Widget.git") == "alice/widget"