---
title: Share links for agentic view generations
type: task
status: completed
description: >-
  Bearer share links carrying a generated view, the submitted instruction, a snapshot of the agent
  session timeline and the run's duration. Built, verified end-to-end against production, and
  deployed (2026-09-06).
base_uri: user:task/league/share-agentic-view-generations.md
created_at: '2026-09-06T18:31:36.016Z'
entity_id: 8b1c4c96-ec15-4500-88cc-a7e6b5531857
finished_at: '2026-09-06T21:18:58.953Z'
observations:
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
priority: Medium
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-09-07T02:09:59.409Z'
visibility_analyzed_at: '2026-11-05T23:50:24.028Z'
---

Share links for agentic view generations are BUILT and committed as `4c68c66fe` in `repository/active/league`, and **not deployed**. What remains is verification against a browser and a real run, plus two routed follow-ups.

## What shipped

One bearer link carries three payloads: the generated view, the instruction the user submitted, and a snapshot of the agent session timeline. Both domains ride it — `data_view` and `plays_view`, off the job row's `view_kind`.

- `db/adhoc/2026-09-06-create-view-generation-shares.sql` — applied to `league_production` 2026-09-06. It is the ONE home for the design rationale; read it before changing any of this.
- `api/routes/view-generation-shares.mjs` — create (authenticated, owner-only, idempotent per generation), read (anonymous), revoke (owner-only).
- `libs-server/data-views/generation/project-timeline-entries-for-share.mjs` — the disclosure allowlist.
- `libs-server/data-views/generation/snapshot-generation-timeline.mjs` — pages the whole timeline, refuses a truncated one.
- `app/views/pages/view-generation-share/` and the route `/shared-generations/:share_id`.
- Share button in `app/views/components/view-generation-control/`.
- 37 specs across `test/view-generation-shares.spec.mjs` and `test/view-generation-share-timeline-projection.spec.mjs`.

## The rulings, so they are not re-litigated

- **Bearer capability, no auth on read.** The unguessable `share_id` IS the credential, the same model `GET /data-views/:view_id` and `/u/{hash}` already use. One sharing concept in this app, not two.
- **The timeline is SNAPSHOTTED at share time, never proxied.** League reads generation threads as their OWNER, so that read returns full content to any caller it lets reach it and is not an authorization boundary.
- **The view RE-EXECUTES for the viewer** under their own entitlement, exactly as a shared saved view does. The run's record is frozen; the data is current.
- **Host paths in tool output are accepted** — operator ruling, 2026-09-06.
- **The query branch is refused.** Zero of 71 completed generations have taken it, and sharing it would publish generated SQL on an anonymous link.

## Remaining work

- [ ] **Browser pass on `yarn dev:live`.** Nothing here has been exercised against a real browser, and both the share button and the `page_header` prop added to the data-views and plays pages are client-path changes. `docs/guides/spa.md` requires it.
- [ ] **One real end-to-end share.** Mint a share against a live completed generation and open the link anonymously. The specs stub the timeline reader, so the real `read_generation_timeline` path is unproven against production base.
- [ ] **Run duration on the shared page.** `AgentSessionTimeline` gained a `duration_ms` prop; the live panel passes it and the shared page cannot, because the share row does not store `duration_milliseconds`. Needs a column, so it needs DDL and an operator decision.
- [ ] **Deploy.** Human-gated; read `docs/guides/ship.md`.

## Cautions

- The repo is PUBLIC. Nothing about ██████████████ ████████ or an unfixed security finding goes in a file there.
- DDL, the schema export and the code that depends on them ship in ONE commit.
- `yarn test:isolated`, never `yarn test`.
