Skip to content

Releases: caty-ai/x-collector

v0.8.1: calendar per-day fallback removed; one Bearer helper for the upstream routes (#152, PR #154)

Choose a tag to compare

@shojikumaru shojikumaru released this 11 Sep 07:23
ac93cb6

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

  • /calendar month indicators never fan out to per-day latest?date= requests any more. Any month-fetch error (including the BFF's coded 404 UPSTREAM_ROUTE_MISSING) shows the existing banner with the whole month known:false and is not cached; the BFF keeps emitting the coded 404 as an operator signal.
  • latest and month upstream routes share one Bearer check (src/lib/auth/newsletter-api-key.ts): same key order (NEWSLETTER_API_KEYDIGEST_API_KEYFEED_API_KEY), production 401 without a key, once-per-route warning outside production, constant-time compare, auth evaluated before query parsing. latest responses are byte-identical to v0.8.0.

Removed

  • fetchDayIndicator, MonthEndpointMissingError, the source field of the month-indicator result, and the "temporary fallback" sentences in docs/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 test on main ac93cb6: 952 tests, publication gate OK; tsc --noEmit clean 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)

Choose a tag to compare

@shojikumaru shojikumaru released this 09 Sep 15:21
b756032

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 ascending days[] with JST day labels ({ date, status, bindingsCount }), newest-updatedAt tie-break, meta.status null/published. An empty month is 200 { 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), separate newsletter-month throttle (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 becomes 404 {"error":"Month summary not found","code":"UPSTREAM_ROUTE_MISSING"} + x-bff-month-fallback: upstream-route-missing in every auth mode, with an operator warning in the server log.
  • Reader contract NewsletterMonthSummaryResponseSchema; docs docs/api-contract-ui-v1.md §1b and docs/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)

Choose a tag to compare

@shojikumaru shojikumaru released this 08 Sep 19:49
0804ea7

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)

Choose a tag to compare

@shojikumaru shojikumaru released this 08 Sep 15:38
5e26e80

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)

Choose a tag to compare

@shojikumaru shojikumaru released this 08 Sep 15:37
935354d

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)

Choose a tag to compare

@github-actions github-actions released this 08 Sep 09:42
a21f790

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/latest gains two opt-in query params: status=published (drafts → 404 on slug / date / latest; the "any edition with contentMd" fallback is skipped) and projection=public (allow-list field pick; markdown drops x-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.
  • NewsletterViewerPanel sends date=<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):tag with 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)

Choose a tag to compare

@shojikumaru shojikumaru released this 07 Sep 13:59
7338eb4

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 stars job holding contents: write and nothing else (the only credential shape GitHub accepts for GET /repos/{source}/stargazers, measured); decide/act stay contents: none.
  • §4.3 / caller: permissions.contents: write is a ceiling materialized only by stars; workflow_dispatch added 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)

Choose a tag to compare

@shojikumaru shojikumaru released this 07 Sep 05:57

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)

Choose a tag to compare

@github-actions github-actions released this 06 Sep 17:27
dc42927

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)

Choose a tag to compare

@shojikumaru shojikumaru released this 06 Sep 16:44
809c875

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.