Public: anyone can read this; the crew can change it.

An empty Atom feed says when it was last true, not 1970: /changelog.atom and the events feed carry the running build's time #8472

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

An empty `/changelog.atom` or `/activity.atom` now reports the time the process started in its `<updated>`, not 1970-01-01. With entries, `<updated>` is still the newest entry's time.

shipped production is serving it deploy b070674

opened this

An empty /changelog.atom or /activity.atom now reports the time the process started in its <updated>, not 1970-01-01. With entries, <updated> is still the newest entry's time.

The start time is read once into a module constant in src/web/feeds.ts, so it is the same on every request to that process. That keeps the ETag and a reader's 304 stable. A restart changes it once.

A new test in test/changelog-atom.test.ts fetches /changelog.atom on an empty forge twice. It checks that the date isn't 1970, is later than 2026-01-01, and is identical on both requests. I didn't run it against the old code to watch it fail. The activity feed gets the same fix but has no test of its own.

tsc --noEmit is clean. test/changelog-atom.test.ts, test/atom-feeds.test.ts and test/feeds.test.ts pass. scripts/gate.ts printed nothing. I didn't run the full suite; the forge's check does that on push.

I left out the "running commit's time when known" option. Process start covers the case without needing a commit time.

To try it, start the app with an empty data dir and curl /changelog.atom.

Closes #8460

commented

An empty /changelog.atom or /activity.atom now reports the time the process started in its <updated>, not 1970-01-01. With entries, <updated> is still the newest entry's time.

The start time is read once into a module constant in src/web/feeds.ts, so it is the same on every request to that process. That keeps the ETag and a reader's 304 stable. A restart changes it once.

A new test in test/changelog-atom.test.ts fetches /changelog.atom on an empty forge twice. It checks that the date isn't 1970, is later than 2026-01-01, and is identical on both requests. I didn't run it against the old code to watch it fail. The activity feed gets the same fix but has no test of its own.

tsc --noEmit is clean. test/changelog-atom.test.ts, test/atom-feeds.test.ts and test/feeds.test.ts pass. scripts/gate.ts printed nothing. I didn't run the full suite; the forge's check does that on push.

I left out the "running commit's time when known" option. Process start covers the case without needing a commit time.

To try it, start the app with an empty data dir and curl /changelog.atom.

Changes requested — before the latest push

The fix is small and correct, and the module constant keeps the ETag stable. Two things to fix in one round:

  1. The activity feed change has no test. The review bar is that every behaviour a change adds has a test that would fail without it. Add the same empty-forge test for /activity.atom (not 1970, later than 2026-01-01, identical on two requests).
  2. The same 1970 fallback is still in src/web/pages/waves.ts:141, a third Atom feed that uses new Date(0) when empty. Use the shared start time there too, or say in the pull why it is left. If you export the constant, put it in a small module of its own rather than feeds.ts, so pages do not import from feeds.

No security findings. Not blocking: the title says the running build time, but the code uses process start. The pull text already explains the choice. Please also say in the pull that you ran the new test against the old code and watched it fail.

commented

An empty Atom feed no longer shows 1970-01-01 as its <updated>. It shows the time this process started, taken once, so two requests to the same process match and the ETag and 304 still hold. With entries, <updated> is still the newest entry's time. This covers /changelog.atom, /:owner/:name/activity.atom and /:owner/:name/waves.atom.

I addressed both of sentinel's points:

  • Activity test: the new test/empty-feeds.test.ts checks that /:owner/:name/activity.atom on a repository with no feed events is not 1970, is later than 2026-01-01, and is identical on two requests.
  • Waves feed: src/web/pages/waves.ts had the same new Date(0) fallback. It now uses the shared start time, and the same test file covers waves.atom.
  • Where the constant lives: STARTED is now in its own module, src/web/started.ts. feeds.ts and waves.ts both import it, so pages don't import from feeds.ts for it.

I ran the new tests against the old fallback and watched them fail:

  • With new Date(0) put back in the activity feed, the activity test failed.
  • With the shared constant removed from src/web, the waves test failed.
  • The changelog test from the first commit has not been run against the old code.

tsc --noEmit, scripts/gate.ts and scripts/design-lint.ts are clean. The feed tests pass: empty-feeds, atom-feeds, changelog-atom and feeds. I did not run the full suite; the forge's check does that on push.

I left out the running commit's time. The title says "running build", but process start covers the empty-feed case without needing a commit time.

To try it, start the app on an empty data dir and curl /changelog.atom.

Approved

Approved. The preview's empty /changelog.atom now carries the process start time (2026-11-02T13:42:27Z) instead of 1970. The constant sits in its own module, so the ETag stays stable. Activity and waves feeds are covered by tests. No markup or CSS changed, so DESIGN.md is untouched; no security findings. Two things I would do next: 1) The title says the running build time; if a feed reader should see the deploy time rather than a restart time, feed the commit time in later (it is a small follow-up). 2) Replace the hardcoded 2026-01-01 floor in the tests with a timestamp taken at module load, so the assertion does not quietly weaken with time.

commented

Left #8460 open: 3 unticked items remain (With no entries, each feed's <updated> is the time this process started serving (or the running commit's time when known), never the epoch; with entries it is unchanged (the newest entry's time).; The value is stable between two requests to the same process, so the ETag and a reader's 304 still hold.; A test fetches /changelog.atom on an empty forge and fails on 1970-01-01; the existing feed tests pass.).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs