Extends v0.4.0 without a second request: the sidebar is updated client-side
from the rows the existing /feed/updates poll already returns.
- Each new row's data-source drives the sidebar: per-source + "All sources"
unread counts bump; a first-time source is inserted into the list
(alphabetically). Reuses the existing count-badge pattern.
- sourceLinks is now live-queried (was cached at load) so sources added live
stay keyboard-navigable.
- No endpoint/model change. 142 tests pass; feed renders.
Caveat: while filtered to a single source, other new sources appear only on
reload (the poll is scoped to the selected view).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New artifacts appear at the top of the feed without a manual refresh.
- GET /feed/updates (session-authed): new artifacts since a timestamp marker,
owner-scoped and filter-aware (source/label/kind/q), returned as row HTML.
- Feed JS polls every 5s, paused while the tab is hidden (immediate poll on
refocus). Prepends new rows into today's group without touching the selected
row or the preview iframe — what you're reading stays put and selected.
- Fresh rows show "now", aging into their real time after ~3 min; brief
highlight on arrival.
- Extracted _artifact_rows.html partial, shared by the day-group render and the
updates endpoint, so live rows match exactly.
- Polling chosen over SSE/WebSockets: zero infra on sync-WSGI + SQLite (see
planning/next_steps for the SSE upgrade path). 142 tests pass; feed page +
endpoint verified.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removes the "Daybook" name from everything user- and agent-facing, since no
agents are configured yet and this is the cheap moment to do it.
- UI brand, docs, README, CLAUDE.md -> AgentFeed.
- Ingest env vars DAYBOOK_URL/TOKEN/SOURCE/DATA_DIR/BIND_ADDR/HOST_DATA_DIR/
KEY_PROVISIONING_API -> AGENTFEED_* (token *values* unchanged).
- Skill: skills/daybook-posting -> skills/agentfeed-posting, daybook_post.py
-> agentfeed_post.py (+ scripts/ wrapper and its test).
- static/daybook.css -> static/agentfeed.css; localStorage daybook.* ->
agentfeed.*; templatetag daybook_extras -> agentfeed_extras; multipart
boundaries; json/csv viewer element ids; daybook_exception_handler ->
agentfeed_exception_handler; compose service/container -> agentfeed.
- Key-provisioning API now OFF by default (independent of DEBUG); enable with
AGENTFEED_KEY_PROVISIONING_API=1 on test installs only.
- Posting helper now points at Settings -> API Keys.
Deferred on purpose (a later, separate step): the Django package
`daybook_project`, the `/opt/daybook` install path, and the Forgejo repo name.
The sibling AGENT_DAYBOOK__LLM_TEST name is intentionally untouched.
Full suite: 129 passing; live server verified serving under the new name.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replace the gear/username button with a round initials avatar (per-user
deterministic color via a new daybook_extras template filter); dropdown
now shows the username and keeps Settings/About/theme/logout. Sets up an
optional profile photo later.
- Regroup the settings nav into "You" (Account, API Keys, Storage, Demo
Data) and a superuser-only "Admin" (Users), About separate — the split
now reflects who each setting affects, not a flat list.
- Register ApiKey (key read-only) and TagColor in Django admin so /admin/
is complete as the operator break-glass tool, distinct from the themed
Settings product surface.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the single per-user DRF token with named, individually-revocable
API keys, so you can run one key per agent and cut off a leaked one without
disrupting the others.
- New ApiKey model (user, name, dbk_-prefixed key, created_at, last_used_at).
Data migration copies every existing authtoken 1:1 into a "default" named
key with the same value, so no client (incl. the sibling test project's
hardcoded test-user key) needs reconfiguring.
- Auth (resolve_token_user) resolves against ApiKey and stamps last_used_at,
throttled to one write/minute.
- Settings -> API Keys: table with name/key/created/last-used + per-row
revoke and a create form; keys viewable on demand. Settings -> Account now
links here; Settings -> Users issues a named initial key.
- Gated provisioning API for test installations: GET/POST /api/keys and
DELETE /api/keys/{id}, controlled by DAYBOOK_KEY_PROVISIONING_API (unset ->
follows DEBUG, so off in deployment). Advertised via key_provisioning_api
in /api/capabilities; 403 when disabled.
- Docs (api/deployment/quickstart/posting-helper), SKILL.md, and env.example
updated from "token / Settings -> Account" to "key / Settings -> API Keys".
- Tests: new API + UI suites for keys; existing token-based tests moved to
ApiKey. Full suite 129 passing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Single source of truth: __version__ in daybook_project/__init__.py, starting
at 0.1.0. Surfaced in two places from that constant:
- Settings -> About page (logo, name, version, description), in the settings
nav and linked from the gear menu.
- GET /api/capabilities now includes "version", so the deploy agent / tester
can confirm which version is actually running.
Release flow: bump __version__, commit, `git tag vX.Y.Z`, push tag, deploy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When a single source is selected the row's source column is hidden, so the
sidebar now renders 112px (7rem) narrower and the reclaimed space goes to
the preview pane — instead of the sidebar staying the same width and just
widening the title. One stored "base" width drives both modes (wide =
stored, source-selected = stored - 112, floored at 150px); dragging the
splitter in either mode adjusts that base directly, so the width stays
user-settable in whichever mode and the modes track each other by the fixed
offset. Avoids having to re-resize every time you switch modes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generated a transparent PNG set from the source icon (a JPEG with a baked-in
checkerboard) by keying out the background on saturation — the arrow is
strongly saturated (0.47-0.68) while the grey/white background is 0.00, so
the cutout is clean. Produced static/logo.png (top-bar, natural aspect),
static/favicon.png (32px), and static/apple-touch-icon.png (180px).
Wired favicon + apple-touch links into all three page heads (feed, settings,
login) and placed the logo next to the "AgentFeed" title in the top bar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When a single source is selected, every row in the middle sidebar repeats
that same source, so the source column is pure waste — the pane header
already names the source. The column now only shows under "All sources"
(where it's needed to tell rows apart); selecting a source hides it and
gives the width back to the artifact title. Also drops the now-dangling
row-main border-right in that state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The UI stylesheet already centralized its palette in a :root block, so this
mostly meant (1) migrating the ~30 colors still hardcoded in rules into
variables so they flip in one place, and (2) adding a [data-theme="dark"]
override palette. Artifact rendering is untouched — those use the separate
static/themes/*.css and the preview backdrop stays white by design, since
artifacts (charts, reports) are authored light.
- Toggle lives in the gear-menu dropdown (Dark mode / Light mode), persists
to localStorage.
- A tiny inline script in each page <head> (feed, settings, login) applies
the stored theme before first paint, so dark-mode users never see a white
flash on load.
- color-scheme: dark on the dark palette makes native form controls
(inputs, buttons) render dark too.
- Semantic accents (kept=green, shared=blue, today, danger) got
dark-appropriate variants; status/data-viz colors (usage bar, tag chips)
and the white artifact backdrop are intentionally left as-is.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Any artifact can now be made publicly viewable via a share link, no login
required - opt-in per artifact, toggled from the feed UI next to Keep.
- Artifact.share_token: nullable, unique, high-entropy (secrets.token_urlsafe(32)).
NULL = not shared; SQL treats each NULL as distinct so uniqueness still
holds for the many not-shared rows.
- New public route GET /s/<token> (shared_artifact_view), completely
unauthenticated, serving the same rendered/raw content as the owner
route via a shared serve_artifact_file() helper.
- toggle_artifact_share: generates/clears the token: mirrors
toggle_artifact_keep's pattern.
- Fixed a real gap this surfaced: embedded images in a shared artifact's
content would otherwise break for an anonymous visitor, since asset_view
was owner-only. It now also allows access when the asset's parent
artifact is currently shared - unattached (orphaned) assets stay private
regardless.
- serialize_artifact now reports is_shared/share_url so the API reflects
sharing status (read-only for now; toggling stays UI-only).
- Feed UI: Share button (mirrors Keep's toggle interaction), a copyable
share-link box that appears when shared, and a "shared" badge on the
artifact row - distinct blue accent from Keep's green so both can be
visible on the same row without confusion.
Verified live end-to-end (toggle on/off, public access, fake-token 404,
old-link-dies-on-unshare, embedded-asset access before/after sharing)
before writing the 12 automated tests in tests/views/test_sharing.py.
Also fixed two unrelated stale spots noticed in docs/api.md while adding
the Sharing section: the example response was missing is_kept/size_bytes,
and the raw-content table didn't list json/csv (added earlier this
session but never documented there).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Peter needed a second user for throwaway testing without going through
Django admin each time. Superusers now get a "Users" tab in Settings
(hidden for regular users) with a create-user form and a list of existing
accounts. New users are regular (non-staff, non-superuser) by default, with
an optional "Grant admin access" checkbox; creating one immediately issues
their API token and displays it once, since that's the credential an agent
account needs and a human account can otherwise regenerate for themselves
later from their own Settings -> Account.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Daybook: a self-hosted, multi-user Django + DRF app where agents, scripts,
or people publish artifacts and each logged-in user browses their own
time-ordered, label-filterable feed.
This squashes prior local development history (kept privately on a separate
branch) into a single clean starting point for the public repository.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>