Added
-
Export has moved to Settings, and the file is made from the full data. Settings → Site → Export replaces the download button on the dashboard chart. Choose a range (any of the usual views, All time, or your own days, always in your site's timezone), the tables you want and a format: Excel, one sheet per table; CSV, a zip with one file per table; or JSON. The file is built by Pulse's servers from everything stored, not from what the dashboard happened to have loaded.
Every file says what it holds. A Notes sheet in Excel, a
README.txtin the CSV zip and anotesobject in JSON name the site, the range and its timezone, the filters, when the file was made, which days were imported from another tool, and where a change in how Pulse measures falls inside the range. The daily summary now carries visits beside visitors. A number Pulse did not measure is an empty cell, never a zero.Advanced options add the rest: 18 tables (pages, entry and exit pages, sources, channels, UTM source, medium and campaign, countries, regions, browsers, operating systems, devices, languages, goals, events and event properties), which metrics, the daily summary's time grain (hour, day, week or month), the dashboard's own filters, and how many rows per table, up to all of them. The daily summary reaches back to your site's first day; every other table covers up to a year at a time.
Who can export is unchanged, and every export is recorded in your audit log as Exported data. Beside it, Your own tools points at API keys, the
pulsecommand line and AI assistants through MCP. -
Growth reports: a designed report of your site to send to investors, clients or your board. In Settings → Site → Export, choose a period, what to compare it with and which slides to include: headline numbers, twelve months of growth, where visitors come from, what they read and where they are, devices and goals. Pulse makes it once and keeps it as it is, so a report sent in March still says what it said in March. You get a link to a page of slides, and a PDF of the same slides at 16:9 that drops straight into a deck, in a light or dark look you choose for that report. A link can have a password and an expiry, and deleting a report closes its link and deletes its numbers. The person you send it to sees that report only, never your dashboard.
-
Scheduled report emails. Have a report made on the 1st of every month or quarter, covering the one that just ended, and emailed to the members of your team you choose. Each email links to its own report, which never changes afterwards. Anyone else gets the link from you.
Reports and scheduled emails are listed under Your reports, and making, deleting, starting and stopping them is recorded in your audit log.
-
All time — from a page's first day of data to its newest, worked out by the server for each page. Past a year the chart switches to weekly, then monthly points.
-
Ask your AI assistant about your analytics: the Pulse Analytics MCP server. Claude, ChatGPT, Cursor, VS Code, Microsoft Copilot Studio and Mistral Le Chat can now read your Pulse numbers. Add
https://pulse-api.ciphera.net/mcpto your assistant, sign in with your Ciphera account, and choose on a Pulse screen which workspace — and which of its sites — it may read. There is nothing to install.It can read, and nothing else. Seven tools: your sites, totals for a period, a daily series, a breakdown (pages, entry and exit pages, referrers, channels, countries, regions, browsers, operating systems, devices, languages, UTM source, medium and campaign), realtime visitors, your install snippet, and a search of the Pulse docs. No tool changes anything in Pulse.
Text your visitors sent is marked as theirs. Page paths, referrers, campaign tags and languages come from visitors' browsers, so they reach the assistant cleaned of invisible characters and labelled as visitor-supplied data, never as instructions.
You can take it back at any time. Settings → MCP lists every connected assistant, who connected it and when it was last used; Disconnect takes effect on its next request. Connecting needs the Owner or Admin role, and each person can connect up to 3 apps to a workspace — they do not count against your API keys. An API key also works, for scripts and clients without sign-in.
Where the numbers go is your choice. An assistant receives the numbers it asks for; if it runs outside the EU, so do those numbers. Pulse itself never sends your data to an AI model. Read MCP privacy and security before you connect, and the setup guide for each assistant.
-
The public read API has a breakdown route.
GET /api/public/v1/sites/{id}/breakdownreturns the top rows of one dimension — the same dimensions as above — for a period, with optional filters. It is additive, like every change to the public API, and it is what the assistant's breakdown tool calls. -
Choose how long a returning reader is recognised (retired 27-10-2026). Settings → Privacy had a Visitor identity panel: Session only, 24 hours, 7 days or 30 days. Until a site chose, it kept the calendar-month behaviour that ran from 26-08-2026 to 26-10-2026: a returning reader was recognised for the rest of the calendar month in the site's timezone, and the menu showed that as Calendar month (current). A visitor is now recognised for one day at most (see A visitor is recognised for one day, at most, under Changed). This entry is kept as history.
A window was a ceiling, not a promise. A reader first seen near the end of a window was recognised for less than it, exactly as a reader first seen on the 30th was recognised for one day. Every sentence in the product said "up to".
Session only changed what "visitors" meant on that site. No visitor identity was written at all, so a reader was counted once per day and never recognised on a later visit: the number became daily session counting, the way it was for every site before 26 August 2026. The dashboard's Unique visitors definition, the Visitors page and the privacy-policy snippet all said so on a site set that way, rather than asserting the month. The public read API's
visitorsfield kept its name and its shape; on such a site it inherited the same meaning, and the day you changed the window was a measurement boundary for that site: identities before it could not be re-derived, so a range that crossed it counted a returning reader once on each side.Changing the window was deliberate and recorded. The panel said what the change cost before you saved it: every identity was re-minted from that moment, readers recognised under the old window counted as new people, and nothing could be applied backwards. Every change was written to your audit trail.
-
Optional interaction capture: see what visitors did, not only which pages they saw. A second, optional script records the label of a button or link that was clicked, how much text was copied and which forms were submitted — and the visit trail describes them in place.
It is not part of your tracking tag and does nothing until you add it. Settings → Site → General has a switch that writes the extra
<script>line for you, with a separate switch for each of the three kinds.What it never records, by design and pinned by tests: anything you type, the text that was copied, any form field's value, any form field's name, and anything about where an element sat on the screen — no CSS selectors, no coordinates.
What it strips before anything is sent, in the visitor's own browser: email addresses become
[email], long digit runs become[number], and labels are cut to 60 characters. Adddata-pulse-ignoreto any element and nothing inside it is ever recorded, at any depth.The main script is unchanged and still under 3 KB gzipped — the new code is a separate file, so a site that does not want interaction capture pays nothing for it.
-
A visitor's visits now read oldest to newest, and their steps group by page. The Visits list was the only thing on the visitor page running newest-first, while the month ribbon above it reads day 1 to 31 and the steps inside each visit read forwards in time — so you went down the steps forwards and up the visits backwards. Page 1 still holds the most recent visits; it just reads in the same direction as everything around it.
Nothing was ever shown twice. Opening a visit used to print one row per event, and a custom event carries the page it fired on — so a page with two events on it appeared on three consecutive rows. Now a row is a page, with the events that fired while it was open listed beneath it. One real example went from 17 rows to 8, and the "—" that used to sit in the duration column of every event row is gone: an event has no duration to report, which is what the dash was saying nine times over.
A page you genuinely visited twice still appears twice, because those are two separate pageviews.
-
Filter a visit's steps by type. An expanded visit now carries small counters — Pages, Outbound, Downloads, Events — and clicking one hides or shows that kind. The counts describe everything loaded and do not change as you filter, so a counter you switched off can always be switched back on. The last active one cannot be switched off, because an empty list looks identical to a visit that recorded nothing.
-
Outbound clicks and downloads are described in words. Instead of an event name beside a
urlchip beside apage_pathchip repeating the row's own path, a step now reads "Left for stripe.com/pricing" or "Downloaded price-list.pdf".Your own custom events are unchanged, and deliberately so: only you know what
checkout_stepmeans, so Pulse shows its name and every property rather than guessing at a sentence. The distinction is drawn from the event's exact shape, not its name — one site sends an event calledoutbound_clickthat is about garments.
Fixed
-
When the dashboard failed to load, the error replaced the whole page, including the date picker and the realtime toggle, so the only way to try another range was to edit the address. The toolbar now stays above the error, and Retry is unchanged.
-
Uptime and Pages offered Last 1 hour and Last 24 hours over data kept by the day, and showed whole days under those labels. The rows are gone (#742).
-
Journeys offered Today, which was always empty: journeys for a day are built after it ends. It is now greyed, and a remembered Today shows yesterday there.
-
A custom range longer than a page can load was accepted by the calendar and then refused by the server. The calendar now stops at the page's limit, and a longer range carried over from another page is shortened to it, keeping its end date.
-
Visitors listed Last 1 hour and Last 24 hours twice, and opened with its selected row out of sight below the fold.
-
On CDN, a range reaching back more than a year would have failed the Served from card, because Bunny answers for a year at most. The card now shows the last 12 months of such a range and says "last 12 months".
-
The line connecting the steps of a visit now runs through them. It sat 12 pixels to the left of the dots it was joining.
-
Visitors — a per-visitor view of your own analytics, off by default. A new page under Analytics (
G V) lists the readers seen in a range and drills into one of them: their visits, the pages of each visit in order, dwell per page, and any custom events they fired with their full properties. There is a live mode with rolling windows down to the last 30 minutes.This changes what Pulse will show you, not what Pulse collects. Every column the page reads was already being written for every site; the switch controls whether anyone can read it at visitor grain. It is off for every site, including existing ones, and turning it on is a deliberate act by a site owner that is recorded in your organisation's audit trail. Settings → Site → Privacy → Visitor views.
What a "visitor" was here, exactly (26-08-2026 to 26-10-2026). A server-derived pseudonymous key, re-minted at the start of every calendar month in your site's timezone. It carried no name, no email, no account, no cookie and nothing stored on the reader's device, it could not be linked to the same person on another site, and at the end of the month it stopped existing: a returning reader came back as a new visitor, under a new name. The page said so on its face rather than in a footnote. History began 26 Aug 2026, the day monthly identity was introduced; the date picker did not offer earlier days, because earlier rows had no monthly key at all and showing them would have labelled per-day identities as if they were per-month ones. Since 27-10-2026 each profile covers one IP address and browser on one day (see A visitor is recognised for one day, at most, under Changed).
What it deliberately cannot reach. Visitor-level data never appears on a public share link, in the public read API, in an export, or on the internal admin surface — four exclusions pinned by tests rather than by convention, because Pulse runs a live public demo through the share surface. Sessions Cerberus has convicted stay invisible here exactly as everywhere else.
Some of our own wording had to change with it: several pages said Pulse keeps "no individual records" or is "architecturally incapable of identifying individual people". The second half of that was always the load-bearing part and is unchanged — Pulse still cannot tell you who someone is — but "no individual records" stopped being true the moment this page existed, so it has been rewritten rather than left to age.
Changed
-
A visitor is recognised for one day, at most. From each site’s own midnight at the start of 27-10-2026, Pulse derives one id per visitor per day from the IP address and browser, with a random key made for that site and that day. Five minutes after the site’s day ends, Ciphera deletes the key and keeps no copy of it, so Pulse cannot recompute that day’s ids. Requests from the same IP address and browser are one visitor and one session within a day, and a reader first seen at 23:50 is recognised for ten minutes. No visitor id is written any more.
Visitors over a range add up each day’s unique visitors, so a returning reader counts once for each day. This is the one rule for every day since a site joined Pulse.
visitor_idis NULL on every row written before a site’s switch to one-day identity: the monthly ids of 26-08-2026..26-10-2026 were nulled on 27-10-2026, day-state and the day archive were rebuilt, and multi-day visitor figures for that period are restated upward. Imported history keeps the visitor figures its source reported. The public read API’s and MCP’svisitorsfield keeps its name and type, so there is no wire change.The identity window setting is retired: Session only, 24 hours, 7 days, 30 days and calendar month are gone, and values stored on sites have no effect. Tracking script 1.7.0 keeps nothing in the browser (no cookie, session storage or local storage) apart from the opt-out flag a site owner sets in their own browser, only when they open their own site with
?pulse-ignore; a reload within five seconds still counts once because the server applies that rule. Visitor views keep working, but each profile covers up to one day: profiles of 26-08-2026..26-10-2026 were rebuilt as one-day profiles on 27-10-2026, so a link to a month-long profile no longer resolves.In the dashboard: Settings → Privacy has no Visitor identity panel. The Visitor views caption now says how long a reader is recognised, and a note under the privacy-policy text asks you to replace it if you pasted the earlier version. The Visitors page reads "Data begins 26 Aug 2026 · each profile covers up to one day" and no longer shows a "% returning" share, which only ever described the rows on screen. A visitor's page shows when they were first seen, with no month ribbon and no reset date. On narrow screens the dot field's caption wraps above the dots instead of running into the live count.
-
One view switcher, the same on every page. The date menu now lists the same twelve rows everywhere: Today, Yesterday, Last 7 days, Last 30 days, Last 3 months, Last 12 months, All time, then This month, Last month, This year, Last year, then Custom range…. It no longer scrolls, and Custom range… opens the calendar with a way back to the list. Dates read "23 Sep" (the year only when it is not this one).
A row a page has no data for is greyed, with the reason — never hidden. Search Console reports each day about two days late, so Search greys Today and Yesterday; journeys are built overnight, so Journeys greys Today; visitor history starts 26 Aug 2026. When a range starts before a page's data or ends after it, the button says so: "Last 12 months · since 26 Aug", "Last 30 days · through 24 Sep".
Removed from the menu: Last 1 hour, Last 24 hours, Last 28 days, Last 6 months, Last 16 months, Last week, Last quarter, Week to date and Quarter to date, and the page-specific groups on Search, CDN, Uptime and Visitors. Links that carry them still open, and the button shows their dates rather than the word "Custom". Performance keeps its own check stepper.
-
One memory for the view. Pick Last 7 days on any page and every page opens on Last 7 days — on every site. A custom range, or one moved with the arrows, follows you until the tab closes. Opening a shared link never changes what you picked. On a page that has no data for your view, Pulse shows the closest view that does and names it on the button — Today on Search shows "24 Sep · latest day", on Journeys "Yesterday · latest day" — without changing what you picked.
-
Realtime is the last 5 minutes, for the count and the view alike (the view was 30 minutes, the count 5, so the two could disagree side by side). The live count is smaller — a dot and the number, grey at zero — and it is still how you enter realtime. On Visitors it sits beside the view switcher and replaces the page's own live windows (30 minutes, 1, 6 and 24 hours). A realtime block with nobody in it says so in one line: "Nobody on the site in the last 5 minutes."
-
Shared dashboards show the same twelve rows, with Today, Yesterday, Last 7 days and Last 30 days available and the rest greyed: "A shared dashboard shows fixed ranges." The live count under the site name is the same small dot and number, for display only.
-
Share links open in Pulse's own dashboard. A link shows the pages it shares in a read-only version of the dashboard, with the same charts and cards you see. Its side rail lists only those pages, and a page the link does not share says "This page isn't shared." What a link shares, and who can open it, have not changed.
-
The live demo is the real dashboard, on a sample site. pulse.ciphera.net/demo opens every page of Pulse (Dashboard, Pages, Journeys, Funnels, Performance, Uptime, Search and CDN) on Halden Cycles, a bike shop that does not exist. It has thirteen months of generated data, and new visits keep arriving while you look. The demo is labelled Sample data.
-
The top bar reads "Updated 6 seconds ago" instead of "Live · 6 seconds ago": it is about when the page last refreshed, not about who is on the site.
-
The steps of a visit are bigger, and each one branches off the line. In an expanded visit the page path, the sentences beneath it and their marks all stepped up a size, and every step now hangs from the visit's line by a short tick instead of merely sitting under its page. A 14-step visit is about a fifth taller than before; nothing new is boxed or bordered, because the line the eye already follows is what draws the hierarchy.
-
Visit duration measures time people spent, and 04-09-2026 is a measurement boundary. The tracking script used to report the wall-clock time since a page loaded as its time on page. A tab left open overnight counted — even on a laptop that was asleep — and a hidden background tab that reloaded itself after a deploy started a visit nobody was on. Measured on production: 73% of the Pulse dashboard's own summed visit time came from single pages carrying more than 30 minutes, and one page carried eight and a half hours. Two defects in the server's arithmetic compounded it: the first page of a second visit in a day contributed zero instead of its own time, and a multi-page visit counted its first page twice while never counting its last.
Tracking script v1.2.0 now measures engaged time — seconds the page was visible and the visitor active — in bounded one-second ticks, so a sleeping machine, a frozen tab or a walked-away desk adds at most a tick. The clock pauses while a tab is hidden and after two minutes without scrolling, clicking or typing, and resumes on activity. A page that loads hidden is not a pageview until it is shown; a URL rewrite that only changes the query string or hash is state, not a navigation (the dashboard's own metric picker had been minting a pageview per click). A page's time is credited to that page and never exceeds the gap to the next one.
Expect visit duration to step down on most sites and pageviews to step down on single-page apps. Pages recorded before the boundary carry no engaged measurement and cannot be re-measured; they are bounded by their visible time and capped at 30 minutes each, and history is recomputed on that basis — on a few sites the average steps up, because the old arithmetic never read a visit's last page. The public read API's
avg_durationis the same field with the corrected meaning, no wire change, as withvisitorson 26-08-2026. An SRI-pinned embed on v1.1.0 keeps the old bytes and the old measurement until the tag is updated; the rollingjs.ciphera.net/script.jsembed picks the change up automatically. Audit:Pulse/docs/audits/04-09-2026-visit-duration-audit.md. -
Funnels, redrawn and simplified. The funnel page is now one chart and one sentence: tall gradient columns show each step's survivors against the entry total, the loss between steps is drawn as the wedge between columns with the drop and the median time to the next step written in the gap, and the headline — conversion, completed of entered, change vs the previous period, median time to convert — is stated once, above the chart, and nowhere else. The five-tile KPI band and the duplicated daily rails are gone; the daily chart and the drop-off and breakdown panels remain. The drop-off panel now names the step it describes and opens on the step that loses the most visitors. The breakdown panel now shows each segment's end-to-end funnel conversion (it used to follow the selected step, which made the default view read "100% conv" for every row — true only in the useless sense), and every breakdown dimension is available, not a curated seven. List cards carry the same chart in miniature. Conversion rates below 10% now show one decimal — a 0.4% funnel no longer prints "0%".
-
Funnel steps may repeat a page or event — revisit funnels work now. A funnel like
/ → /pricing → /used to be rejected when saving ("a later duplicate step can never be matched") because the engine assigned each pageview to only one step. Matching is now evaluated per step, so a later step completes on any strictly-later matching event. Funnels whose steps don't overlap measure exactly as before; if two of your steps do overlap (say, a "contains" step that also covers an "exact" step's page), sequences the old engine silently missed are now counted — that is a correction, and numbers can step up slightly. -
Page "contains" steps are now case-insensitive, and
%/_match literally. This was the only case-sensitive "contains" in the product, and a literal percent or underscore in the value acted as a hidden wildcard. A contains step may match slightly more than before; exact and regex steps are unchanged. -
Funnel regexes are validated by the engine that runs them. Saving a funnel checks the pattern against the database's regex dialect, so a pattern that saves is a pattern that reads. Previously a pattern could pass the save-time check and then fail on every view of the funnel, forever.
-
Funnels need at least two steps, exact page steps must start with
/, and a site can hold up to 50 funnels. Creating and editing funnels and goals is now recorded in your organisation's audit trail. -
The tracking script sends engagement to a path ad blockers do not cancel, and 26-08-2026 is a measurement boundary for time-on-page and scroll depth. The beacon carrying duration, visible duration and scroll depth used to post to
/api/v1/metrics. EasyPrivacy carries a bare, domain-agnostic substring rule for exactly that path — written for an unrelated vendor, matching ours by coincidence — so uBlock Origin, Brave and everything else shipping that list cancelled the request client-side while the pageview itself landed. Those visitors were counted, and their engagement was not. The script now posts to/api/v1/engagement; the old path stays live server-side indefinitely for scripts already cached at the edge and for SRI-pinned embeds. Expect time-on-page, visible time and scroll depth to step up. That is the instrument widening, not readers behaving differently, and it cannot be backfilled — a blocked beacon never reached us to be recovered. Measured before the change: 89.9% of pageviews carried a duration over 30 days, lowest onciphera.netat 61.1%. The step will be smaller than that gap suggests, because the script also withholds the beacon by design when there is no genuine engagement to report. Ciphera is on no filter list; this was a path-name collision, verified against EasyPrivacy, EasyList, uBlock's uAssets, AdGuard and Disconnect. Analysis:Pulse/docs/audits/26-08-2026-psi-err-blocked-by-client-metrics.md. -
Tracking script v1.1.0. New bytes require a new immutable version, so the SRI-pinned embed snippet now offers
v1.1.0. An existing pinned tag keeps working and keeps posting to the legacy path — a pin is a promise that those bytes never change, so adopting the fix means updating the tag. The rollingjs.ciphera.net/script.jsembed, which carries no integrity attribute, picks the fix up automatically. -
"Unique visitors" counted a returning reader once per calendar month, from 26-08-2026 to 26-10-2026. Visitor identity used to rotate every day, so a returning reader was re-counted once per day (and the public API's
visitorsfield inherited that). From 26-08-2026 to 26-10-2026, identity was deduplicated within each calendar month in the site's own timezone: a returning reader counted once, on the dashboard and in the public read API'svisitorsfield alike (same field, no wire change). Since 27-10-2026 a visitor is recognised for one day at most, and multi-day visitor figures for that period are restated upward as the sum of each day's unique visitors (see A visitor is recognised for one day, at most, under Changed). Session boundaries also moved from UTC midnight to the site's own midnight on 26-08-2026, which ended the long-standing off-by-one between the headline and the daily chart.
Removed
-
Small numbers are no longer hidden anywhere. Every row and every metric now shows at any size, filtered or not. A shared dashboard shows the same top rows your team sees for the same range, a page or a city with one visitor included, and the line naming what it had hidden is gone. The read API, the CLI and the MCP tools answer a filter that matches one visitor with its real numbers, list a page in realtime however few visitors it has, and keep a small day's averages and a small filtered row in the exports. Funnel breakdowns list a value however few entrants it had, and a funnel's Daily chart no longer skips a day with fewer than five entrants. Fields kept for older clients say nothing was withheld (
suppressedisfalse, the export headers are0). Filters stay off on a shared link, and its ranges stay fixed. -
The notification bell and the
/notificationspage are gone. Pulse notifications arrive by email. The emails now link straight into Pulse. You switch off a category's emails in Settings → Account → Notifications, and/notificationsredirects there, so bookmarks and older links keep working. The tour's "Alerts land here" step, theg nshortcut and the command palette's Notifications entry went with the page. Failed-payment, invoice and refund notices go by email to the workspace's billing contact, as they always have; the workspace's other members saw them only in the bell, so they no longer get them. The "Site added" notification is retired: it told the person who had just added a site that they had added one. -
The dashboard's Export button and its PDF are gone. Export lives in Settings → Site → Export now (see Added). The shared dashboard and the live demo lose their Export button too: a shared link is for looking at the numbers, not for downloading them. The old PDF, built in the browser, went with the button.
-
The funnel conversion window is gone — it never did anything. The setting (24 hours to 30 days) shipped in March and was removed from the product in August: session identity resets at your site's midnight, so no conversion could ever span more than one session and every window setting measured identically (verified on production data before removal). Funnels state the real rule instead: a conversion counts when a visitor completes every step within one session. The March entry below is kept as history.
-
The privacy scanner is gone. The Settings > Privacy scan — a single-request check that printed "Privacy score 100" for pages it could not meaningfully judge — has been removed end to end, including its stored results. The Privacy settings tab itself (page rules, path grouping, query-parameter allowlist) is unchanged.
-
Scheduled email reports and outbound webhooks are gone; the Reports tab is now Alerts. Scheduled analytics reports and the notification-webhook integration have been removed. Uptime alert channels — email and in-app, fired when a monitor goes down or recovers — are unchanged and keep their tab (now named Alerts). Two fixes landed with the change: a paused alert channel no longer disappears from settings, and alert channels no longer consume report slots.
-
Custom roles are gone. Roles are now the built-in three — Owner, Admin, Member — assigned through invite links. The Roles view remains as a read-only matrix of what each role can do. Existing memberships were unaffected; the only custom role ever created was a test artifact and was removed.
-
The CDN page's world map is gone. It plotted bandwidth by Bunny edge datacenter, which read as visitor geography and was nothing of the kind. The ranked "Served from" region list — the honest version of the same data — remains, as does the Audience map (which really is visitor geography).
-
The "Visitor recognition" setting is gone. The tracking script never read the storage attributes the control emitted — visitor identification has been fully server-side for months. Removing the control removes the pretense; nothing about tracking behavior changed.
-
The Campaigns card's Export and Build URL buttons are gone. The card's own CSV download and the in-dashboard UTM builder (including the empty state's "Build a UTM URL" button) have been removed; the Source / Medium / Campaign / Term / Content tabs are unchanged. Campaign rows still ship in the dashboard's Export (the Campaigns sheet in the spreadsheet and the Campaigns table in the PDF), and the public UTM builder at
/tools/utm-builderis untouched.
Changed
- A share password no longer travels in the URL. Password-protected share links now authorize only through the short-lived cookie set when the password is entered; a
?password=query parameter is ignored (it used to leak into browser history and server logs). The share page also re-prompts for the password when access expires instead of quietly showing stale numbers.