From 1c7538d54c3cdea824001464c47091798c324742 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Sat, 3 Oct 2026 18:15:27 +0200 Subject: [PATCH] docs(14): record plan-time decisions from research checkpoint --- .../14-domain-jobs-and-external-integrations/14-CONTEXT.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.planning/phases/14-domain-jobs-and-external-integrations/14-CONTEXT.md b/.planning/phases/14-domain-jobs-and-external-integrations/14-CONTEXT.md index 01f17cf..cb6d6b8 100644 --- a/.planning/phases/14-domain-jobs-and-external-integrations/14-CONTEXT.md +++ b/.planning/phases/14-domain-jobs-and-external-integrations/14-CONTEXT.md @@ -49,6 +49,12 @@ Out of scope: sitemap (dropped for Płytarium, D-14), `oauth-identities` GET/DEL - **D-16:** Time is injected. The Discogs rate limiter, its wait budget and retry-after handling, and the match job's re-enqueue all take a clock/sleeper interface. Tests advance a fake clock without real sleeps, and assert the 240 s timeout and the re-enqueue delay as values. - **D-17:** The researcher reads `DiscogsRateLimiter.php` and decides where its state lives, either process memory or Postgres (an UNLOGGED table or an advisory lock), depending on whether PHP's cross-worker guarantee is still needed when one binary runs HTTP and River workers. The choice and its reason go in RESEARCH.md. +### Plan-time resolutions (2026-10-03, after research) +- **D-18:** Golem models are stored in a dedicated `golem15_golem_models` table with a `lagoon.Encrypted` `api_key` (`json:"-"`), an admin list/form, and a one-time importer from the PHP settings row. The PHP settings code is `golem_settings`, not `golem15_golem_settings` (this corrects D-01), and PHP stores `models[].api_key` in plaintext. Feedback settings use the same pattern: a typed singleton table plus an importer, because cabana rejects `colorpicker`/`readOnly`. — **Reversibility:** costly — the table schema becomes the plugin contract. +- **D-19:** Upstream sidecars (D-15) are captured with a recording HTTPS proxy in tide (`summer parity:upstream`). PHP runs through the proxy while cases are recorded, so the sidecars are the real exchanges. `ai-credential/test` and `discogs-credential/test` are re-recorded through it. +- **D-20:** SSRF parity: Go ports PHP `SSRFGuard` exactly. That covers the https requirement, the host allowlist (default `.openai.com` plus the DALL-E blob host, override `GOLEM15_SSRF_ALLOWED_HOSTS`) and the uncaught-exception 500 page on guard failure. Go also adds the fetchguard dial-time private-IP guard on top. Admin Settings models stay trusted (D-05 confirmed). +- **D-21:** Discogs rate-limiter state lives in Postgres: an UNLOGGED table plus one atomic `INSERT … ON CONFLICT DO UPDATE … WHERE … RETURNING`, with the clock passed in (resolves D-17, see RESEARCH). + ### Claude's Discretion - Wishlist digest mail content, locale and template: a straight port of `WishlistDigestJob` and its PHP mail view on the existing postcard mail pipeline. - `prune-notifications` and `reindex` options, output and exit codes: a straight port of `PruneNotifications.php` and `ReindexAlbums.php`, on bonfire with the existing `schedule.go` entry.