Releases: caty-ai/x-collector
Release list
v0.8.1: calendar per-day fallback removed; one Bearer helper for the upstream routes (#152, PR #154)
v0.8.1 — calendar: per-day fallback removed; one Bearer helper for the upstream routes (#152, PR #154)
Follow-up to v0.8.0 (#151). The upstream month route is deployed and the owner confirmed one request per month flip in production (DW10, 2026-09-10), so the deploy-order insurance is gone.
Changed
/calendarmonth indicators never fan out to per-daylatest?date=requests any more. Any month-fetch error (including the BFF's coded 404UPSTREAM_ROUTE_MISSING) shows the existing banner with the whole monthknown:falseand is not cached; the BFF keeps emitting the coded 404 as an operator signal.latestandmonthupstream routes share one Bearer check (src/lib/auth/newsletter-api-key.ts): same key order (NEWSLETTER_API_KEY→DIGEST_API_KEY→FEED_API_KEY), production 401 without a key, once-per-route warning outside production, constant-time compare, auth evaluated before query parsing.latestresponses are byte-identical to v0.8.0.
Removed
fetchDayIndicator,MonthEndpointMissingError, thesourcefield of the month-indicator result, and the "temporary fallback" sentences indocs/api-contract-ui-v1.md§1b /docs/operations.md.
Tests
- Helper suite (env precedence, production fail-closed, wrong/missing Bearer, warn-once per tag, case-insensitive prefix); both routes lock "invalid query + wrong Bearer → 401, no Prisma call" (mutation-checked); coordinator suite covers coded 404 → no fan-out / banner / retry.
Verification
make testonmainac93cb6: 952 tests, publication gate OK;tsc --noEmitclean on both tsconfigs; CI green.- Review: GLM 5.3 / Grok 4.6 / Opus 5, r1 + delta-1, cumulative GO / GO / GO. Writer: Codex gpt-5.6-sol.
Previous release: v0.8.0.
v0.8.0: month-summary endpoint — one request per calendar month instead of 31 (#151, PR #153)
Month-summary endpoint for the public calendar (#151, PR #153) — the anonymous calendar now marks a month with one request instead of up to 31 per-day requests.
Added
- Upstream
GET /api/newsletter-editions/month?month=YYYY-MM[&status=published](Bearer): one query over the JST month bounds, sparse ascendingdays[]with JST day labels ({ date, status, bindingsCount }), newest-updatedAttie-break,meta.statusnull/published. An empty month is200 { days: [] }— the route never returns 404 itself. - Anonymous BFF
GET /api/bff/newsletter-editions/month?month=YYYY-MM:month-only allow-list (2020-01 … the month of JST today+1), separatenewsletter-monththrottle (60 requests / 60 s / IP), pinned body (meta=month/timeZoneForDateParam/status; day =date/bindingsCount), published-only days clamped to JST today+1, every upstream non-2xx normalised. Upstream 404 becomes404 {"error":"Month summary not found","code":"UPSTREAM_ROUTE_MISSING"}+x-bff-month-fallback: upstream-route-missingin every auth mode, with an operator warning in the server log. - Reader contract
NewsletterMonthSummaryResponseSchema; docsdocs/api-contract-ui-v1.md§1b anddocs/operations.md公開モード.
Changed
- Calendar panel: month indicators load through a coordinator that owns the month cache and request sequence (fixes a cache-hit race where a slow earlier month could overwrite a cached one). Days after JST today+1 now render dimmed without an error banner (previously "unknown" + banner). A failed month load is not cached, so flipping back retries.
- Deploy-order insurance: if the web app ships before the upstream, the calendar falls back to the per-day requests only on the coded 404 above. Removal of that fallback is tracked in #152.
Deploy order
Railway upstream first, then web.
Review: five heterogeneous seats (Opus 5, Qwen 3.8 Max, Gemini 3.8 Flash, Muse Spark 1.3, Codex GPT-5.6 Sol) — design frozen after three rounds, implementation GO ×5 on 5a5227b. Previous release: v0.7.3.
v0.7.3: supporter-loop caller — sweep twice daily, cron 17 3,15 * * * (contract v2.0, #142 A3, PR #149)
v0.7.3: supporter-loop caller — sweep twice daily, cron 17 3,15 * * * (contract v2.0 §4.3/§11, #142 A3, PR #149)
The caller's sweep now runs at 03:17 and 15:17 UTC (12 h apart) on the v2.0 reusable workflow
(caty-ai/.github v0.12.0) with standing catch-up and the invitation quota queue. This completes
the scale lane A1 (v0.7.1) -> A2 (v0.7.2) -> B (.github v0.12.0) -> A3.
Evidence: PR #149 (completion record, three seats GO,
owner risk-reviewed); EPIC #119.
v0.7.2: supporter-loop caller — separate sweep concurrency lane (contract v2.0 §4.3, #142 A2, PR #148)
v0.7.2: supporter-loop caller — separate sweep concurrency lane (contract v2.0 §4.3, #142 A2, PR #148)
The caller's concurrency.group is now conditional: supporter-loop-sweep- for schedule /
workflow_dispatch, supporter-loop- for tier events; cancel-in-progress: false on both.
A burst of Stars can no longer cancel the pending sweep. Cron stays weekly until A3 (after
caty-ai/.github child B).
Declared v0.7.1 at review time; bumped to v0.7.2 because v0.7.0 was taken by PR #145.
Evidence: PR #148 (completion record, three seats),
owner risk-reviewed label.
v0.7.1: supporter-loop contract v2.0 — sweep lane, standing catch-up + invitation quota queue, twice-daily sweep, capacity §16 (#142 A1, PR #147)
v0.7.1: supporter-loop contract v2.0 — sweep lane, standing catch-up + invitation quota queue, twice-daily sweep, capacity §16 (#142 A1, PR #147)
Contract v2.0 (contract_version 2, ledger schema 1) for the X-launch burst: an un-replaceable
sweep lane, standing catch-up (two passes, Q = max(0, 45 - B), whole-sweep work budget),
invitation-limit 422 -> deferred-quota, GET->read->render->PUT regeneration, sweep-state
latch + one summary, capacity ceilings and owner rules (§16).
Declared v0.7.0 at review time; v0.7.0 was taken by PR #145 (2026-09-08), so this is v0.7.1.
Evidence: PR #147 (completion record, five-seat GO
on e3bdea1 + approval-URL commit b9b4931); checkpoint #7 second pass
#119 (comment); owner approval
#147 (comment).
v0.7.0: newsletter public reader — published-only status constraint + public JSON projection (#91, PR #145)
v0.7.0 — newsletter public reader: published-only status constraint + public JSON projection (#91, PR #145)
Follow-up to #85 (opt-in public reader mode). Main commit a21f790 (squash of a775c6d + 0b212e9).
Changed
- Upstream
GET /api/newsletter-editions/latestgains two opt-in query params:status=published(drafts → 404 on slug / date / latest; the "any edition with contentMd" fallback is skipped) andprojection=public(allow-list field pick; markdown dropsx-edition-id/x-edition-slug). Any other value → 400. Callers without the params get byte-identical responses (locked by exact-equality tests). - The public BFF builder always sends both params; the anonymous BFF, the
/a/loader and the og-image guard inherit them. The BFF also re-applies the same projection and pins the top level to{meta, edition}, so the field guard does not depend on Railway deploy order. - Public field set: edition =
editionDate, title, status, publishedAt, bindingsCount, contentChars, contentMd?, items?; item =section, position, title, titleJa, url, trustLabel. NewsletterViewerPanelsendsdate=<appliedDate>to/api/bff/og-image(Referer becomes a pure fallback).- Also shipped from the Unreleased changelog: Projects shelf under the calendar (#118, default off) and the GitHub release duplicate key
lower(repo):tagwith migration / backfill.
Docs
docs/operations.md公開モード,docs/api-contract-ui-v1.md§1 (params,items[]schema, header sets),docs/changelog.md.
Review
- Five heterogeneous seats (Opus / Codex sol / Kimi / Qwen / Gemini), r1 + delta, zero blocking on 0b212e9. Record on #91.
Deploy note
- Recommended order: Railway API first, then the web app. Either order is safe for field exposure thanks to the BFF re-projection.
v0.6.3: supporter-loop contract v1.11 — sweep-only stars job, caller contents ceiling + workflow_dispatch, per-workflow runs listing (#139, PR #140)
Post-freeze correction after the first live weekly sweep (run 34100523613) failed closed.
- §0-4 / §4.4: the stargazer listing runs in a sweep-only
starsjob holdingcontents: writeand nothing else (the only credential shape GitHub accepts forGET /repos/{source}/stargazers, measured);decide/actstaycontents: none. - §4.3 / caller:
permissions.contents: writeis a ceiling materialized only bystars;workflow_dispatchadded as a second sweep trigger. - §11(a): per-workflow runs listing (repository-wide listing exceeded the 1,000 cap); caller file name frozen; red-run reconciliation = owner deletes the reconciled run.
- §8.3 / §8.4 / §13: probe exceptions named; the wrong implicit-PAT-read sentence corrected; header mirror.
Sibling: caty-ai/.github v0.11.6 (PR #90). Review: 5 heterogeneous seats × 3 rounds, zero blocking. Tracked in #139; follow-up #141.
v0.6.2: supporter-loop contract v1.10 — §8.4 over-scope probe correction (#136, PR #137)
CONTRACT.md v1.10 (post-freeze correction after the first live run): §8.4 no longer requires GET /repos/{reward_repo} to hide permissions.push == true (that object reflects the token owner's role, not the fine-grained grant). The endpoint is a reachability probe; the loop token's Contents 403/404 probe is the push-impossibility proof. Pairs with caty-ai/.github v0.11.5. No permission boundary weakened.
v0.6.1: supporter-loop goes live — mode record-only → live (EPIC #119 checkpoint ④, #134, PR #135)
v0.6.1: supporter-loop goes live — mode record-only → live (EPIC #119 checkpoint ④, #134, PR #135)
Invitations, thank-you comments and SUPPORTERS.md updates are now sent for
non-family supporters. Record-only proof, owner decisions and the 5-seat
review are on EPIC #119. Rollback = the same one line (contract v1.9 §5.4).
v0.6.0 — Projects shelf on /calendar (#118)
New: a Projects shelf on the public reader, directly under the calendar on every breakpoint. Three configured cards with thumbnails (NEWSPAPER_PROJECTS_FEATURED) or, when unset, the latest releases of tagged GitHub sources. OFF by default (NEWSPAPER_PROJECTS_SHELF). /api/bff/projects gates in-route: 404 when off, reader auth, public-only throttle, private/no-store for authenticated callers.
Also: GitHub release items are now keyed by lower(repo):tag (fixes duplicate tags across repos) — two migrations ship with this release; run prisma migrate deploy, then tools/gh-dedup-backfill.mjs (dry-run first) and tools/gh-dedup-proof.mjs. See docs/operations.md#projects-shelf.
PR #133 (Issue #118): 5 heterogeneous review seats × 2 rounds, blocking 0. Port of the upstream shelf feature set, shelf only.