Keep a production run to the adventures you meant
The hosted database is not the local one. It holds other people's stories, and `summary_provider` builds from the adventure owner's Settings, so an unfiltered `--write` against it would spend other people's money rewriting memories they never asked about. `--adventure` could already hold a run down, but only if you knew the ids. `--email` names accounts instead, and every line of the report now says who owns the adventure, so a dry run answers "whose keys would this spend" before anything is written. Guests have no email and stay reachable only by id, which is the right amount of friction for touching a stranger's bank. The other half is written down rather than built: stored API keys are encrypted with AIDND_SECRET_KEY, so a run from a checkout against the Neon database needs the same value the web service holds. With a different one `decrypt_secret` returns "" instead of failing, and every adventure is reported as having no key — a run that looks like it worked and did nothing. The Dockerfile copies backend/app alone, so tools/ is not on the box either way; the recipe is a checkout pointed at AIDND_DATABASE_URL. 629 green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tqgupw5CZGjSZrUTNUd4fW
This commit is contained in:
@@ -121,8 +121,9 @@ def fill_bank(db, adventure, *, count=2):
|
||||
|
||||
|
||||
def options(**overrides):
|
||||
args = dict(write=False, adventure=None, limit=None, include_forgotten=False,
|
||||
embed=False, endpoint=None, model=None, api_key=None)
|
||||
args = dict(write=False, adventure=None, email=None, limit=None,
|
||||
include_forgotten=False, embed=False, endpoint=None,
|
||||
model=None, api_key=None)
|
||||
args.update(overrides)
|
||||
return argparse.Namespace(**args)
|
||||
|
||||
@@ -358,6 +359,25 @@ def test_only_the_named_adventure_is_touched(db, monkeypatch):
|
||||
assert changed.text == "Kaelen entered the crypt 1."
|
||||
|
||||
|
||||
def test_only_the_named_account_is_touched(db, monkeypatch):
|
||||
"""The hosted database holds other people's stories, and each adventure is
|
||||
summarized with its owner's key."""
|
||||
mine = make_adventure(db, email="mine@example.com")
|
||||
theirs = make_adventure(db, email="theirs@example.com")
|
||||
kept, _ = fill_bank(db, theirs)
|
||||
changed, _ = fill_bank(db, mine)
|
||||
monkeypatch.setattr(memorybank, "summary_provider", lambda s: StubSummarizer())
|
||||
assert run_tool(options(write=True, email=["MINE@example.com"])) == 0
|
||||
db.expire_all()
|
||||
assert kept.text == "You entered the crypt 1."
|
||||
assert changed.text == "Kaelen entered the crypt 1."
|
||||
|
||||
|
||||
def test_an_unknown_email_is_an_error(db):
|
||||
make_adventure(db)
|
||||
assert run_tool(options(email=["nobody@example.com"])) == 2
|
||||
|
||||
|
||||
def test_an_unknown_adventure_id_is_an_error(db):
|
||||
make_adventure(db)
|
||||
assert run_tool(options(adventure=[9999])) == 2
|
||||
|
||||
Reference in New Issue
Block a user