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
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:
@@ -27,11 +27,11 @@ def _snippet(id=1, owner=9):
|
||||
async def test_editor_share_can_update_and_writes_as_the_owner():
|
||||
"""The underlying note update is owner-scoped, so a shared editor's own id
|
||||
would match nothing — the authorised write has to be performed as the owner."""
|
||||
from scribe.services import snippets as svc
|
||||
from grimoire.services import snippets as svc
|
||||
note = _snippet(owner=9)
|
||||
updated = _snippet(owner=9)
|
||||
with patch.object(svc, "get_snippet", AsyncMock(return_value=note)), \
|
||||
patch("scribe.services.access.can_write_note", AsyncMock(return_value=True)), \
|
||||
patch("grimoire.services.access.can_write_note", AsyncMock(return_value=True)), \
|
||||
patch.object(svc.notes_svc, "update_note",
|
||||
AsyncMock(return_value=updated)) as mock_update:
|
||||
got = await svc.update_snippet(7, 1, name="formatDuration")
|
||||
@@ -43,9 +43,9 @@ async def test_editor_share_can_update_and_writes_as_the_owner():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_viewer_share_cannot_update():
|
||||
from scribe.services import snippets as svc
|
||||
from grimoire.services import snippets as svc
|
||||
with patch.object(svc, "get_snippet", AsyncMock(return_value=_snippet())), \
|
||||
patch("scribe.services.access.can_write_note", AsyncMock(return_value=False)), \
|
||||
patch("grimoire.services.access.can_write_note", AsyncMock(return_value=False)), \
|
||||
patch.object(svc.notes_svc, "update_note", AsyncMock()) as mock_update:
|
||||
with pytest.raises(PermissionError, match="read-only"):
|
||||
await svc.update_snippet(7, 1, name="nope")
|
||||
@@ -56,10 +56,10 @@ async def test_viewer_share_cannot_update():
|
||||
async def test_viewer_share_cannot_delete():
|
||||
"""delete_snippet returns False rather than raising — its contract is boolean
|
||||
— but a viewer must not be able to bin someone else's record."""
|
||||
from scribe.services import snippets as svc
|
||||
from grimoire.services import snippets as svc
|
||||
with patch.object(svc, "get_snippet", AsyncMock(return_value=_snippet())), \
|
||||
patch("scribe.services.access.can_write_note", AsyncMock(return_value=False)), \
|
||||
patch("scribe.services.trash.delete", AsyncMock()) as mock_trash:
|
||||
patch("grimoire.services.access.can_write_note", AsyncMock(return_value=False)), \
|
||||
patch("grimoire.services.trash.delete", AsyncMock()) as mock_trash:
|
||||
assert await svc.delete_snippet(7, 1) is False
|
||||
mock_trash.assert_not_awaited()
|
||||
|
||||
@@ -68,7 +68,7 @@ async def test_viewer_share_cannot_delete():
|
||||
async def test_unreadable_record_is_not_found_not_forbidden():
|
||||
"""A record the caller can't see at all must NOT be distinguishable from one
|
||||
that doesn't exist — otherwise the error itself confirms it exists."""
|
||||
from scribe.services import snippets as svc
|
||||
from grimoire.services import snippets as svc
|
||||
with patch.object(svc, "get_snippet", AsyncMock(return_value=None)):
|
||||
assert await svc.update_snippet(7, 404, name="x") is None
|
||||
assert await svc.delete_snippet(7, 404) is False
|
||||
@@ -76,9 +76,9 @@ async def test_unreadable_record_is_not_found_not_forbidden():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_merge_requires_write_on_target():
|
||||
from scribe.services import snippets as svc
|
||||
from grimoire.services import snippets as svc
|
||||
with patch.object(svc, "get_snippet", AsyncMock(return_value=_snippet())), \
|
||||
patch("scribe.services.access.can_write_note", AsyncMock(return_value=False)):
|
||||
patch("grimoire.services.access.can_write_note", AsyncMock(return_value=False)):
|
||||
with pytest.raises(PermissionError, match="read-only"):
|
||||
await svc.merge_snippets(7, 1, [2])
|
||||
|
||||
@@ -88,7 +88,7 @@ async def test_merge_skips_sources_owned_by_someone_else():
|
||||
"""Cross-owner merge stays out of scope: a source belonging to a
|
||||
different owner than the target is skipped, not silently folded in and
|
||||
trashed."""
|
||||
from scribe.services import snippets as svc
|
||||
from grimoire.services import snippets as svc
|
||||
target = _snippet(id=1, owner=9)
|
||||
same_owner = _snippet(id=2, owner=9)
|
||||
other_owner = _snippet(id=3, owner=42)
|
||||
@@ -97,9 +97,9 @@ async def test_merge_skips_sources_owned_by_someone_else():
|
||||
return {1: target, 2: same_owner, 3: other_owner}.get(sid)
|
||||
|
||||
with patch.object(svc, "get_snippet", AsyncMock(side_effect=fake_get)), \
|
||||
patch("scribe.services.access.can_write_note", AsyncMock(return_value=True)), \
|
||||
patch("grimoire.services.access.can_write_note", AsyncMock(return_value=True)), \
|
||||
patch.object(svc.notes_svc, "update_note", AsyncMock(return_value=target)), \
|
||||
patch("scribe.services.trash.delete", AsyncMock(return_value=object())):
|
||||
patch("grimoire.services.trash.delete", AsyncMock(return_value=object())):
|
||||
_note, merged_ids = await svc.merge_snippets(7, 1, [2, 3])
|
||||
|
||||
assert merged_ids == [2]
|
||||
|
||||
Reference in New Issue
Block a user