Releases: StartupAPI/startup-api-cloudflare
Release list
v0.5.0 — Configurable sliding session lifetime + on-by-default entitlement freshness
Separates login lifetime (authentication) from entitlement freshness (authorization), which were previously conflated by a hardcoded 24h session that forced a ~daily re-login.
Sessions
- Configurable, rolling session TTL via
session: { ttl }, default 30 days. Sessions renew on activity once less than half the window remains — active users effectively never re-login; idle sessions still expire. session_idis now a persistent (Max-Age) cookie and itsMax-Ageis refreshed on renewal.
Entitlement freshness
- Flattened
freshness: { ttl, cron, webhook }→ per-providerentitlementTtl/entitlementCron/entitlementWebhook. entitlementTtlis now ON by default for entitlement providers — 1 day for Patreon, 15 min otherwise — as a backstop for missed webhooks.entitlementTtl: falsedisables it.- Durations are a named-unit object (
{ days: 30 },{ minutes: 15 }) or a plain number of ms, via a sharedDuration+durationToMs(). Applied to bothsession.ttlandentitlementTtl.
⚠️ Breaking changes
freshness.*config removed →entitlementTtl/entitlementCron/entitlementWebhook.entitlementTtldefault: off → on (1 day Patreon / 15 min other).- Default session lifetime: fixed 24h → rolling 30 days;
session_id→ persistent cookie.
See #111 for full detail.
v0.4.5
Patch — load power-strip.js as an ES module
Changed
- The injected
power-strip.jsscript is now<script type="module" async>. Path detection switched fromdocument.currentScript(null for module scripts) toimport.meta.url, verified in a real browser to still resolvebasePathcorrectly.
Full changelog: #110
v0.4.4
v0.4.3
Patch — Login Credentials section branding + handle
Fixed
- The Login Credentials list now shows atproto with the Atmosphere "union" logo, the label "Atmosphere / ATproto", and the handle with the DID in parentheses (e.g.
alice.bsky.social (did:plc:…)) instead of the old Bluesky butterfly, "Atproto", and a bare DID.
Added
- The atproto handle is now persisted at login (
UserProfile.handle, surfaced vialistCredentials). Credentials created before this release show the DID alone until the next login.
Full changelog: #108
v0.4.2
Patch — fixes atproto login form (regression in 0.4.1)
Fixed
- The "Login with your Atmosphere account" form now submits. The hardened CSP added in 0.4.1 included
form-action 'self', which blocked the form submission: the form posts to our endpoint, which 302-redirects to the user's own authorization server (cross-origin), andform-actionis enforced across the whole redirect chain. Symptom was the form "doing nothing" while navigating to the auth URL directly worked. Removed theform-actiondirective (incompatible with a login form that redirects to per-user auth servers); all other hardening —default-src 'none',frame-ancestors 'none',style-src 'self',nosniff,no-store— stays.
Full changelog: #107
v0.4.1
AT Protocol (Atmosphere) login — fixes & polish
Fixed
- atproto login now works on Cloudflare Workers. Handle→DID resolution used
fetch(…, { redirect: 'error' }), a mode the Workers runtime doesn't implement (it throws), which silently broke*.bsky.sociallogins withCould not resolve handle "…" to a DID. Switched toredirect: 'manual'.
Added
ATPROTO_ENABLEDenv flag to enable atproto per-deployment without editing the factory config (truthy =true/1/yes/on). A factoryatproto: { enabled: false }still overrides it.
Changed
- Styled, theme-aware auth pages. The handle-entry form and a new sign-in error page now follow the user's OS/chosen theme (via
style.cssvariables) instead of rendering bare text. - Failed logins recover in place — a bad handle re-renders the form with the error inline and the handle pre-filled, rather than a dead-end page.
- Rebrand to "Atmosphere" — dropped all "Bluesky" wording; the button reads "Login with your Atmosphere account" and uses the official Atmosphere logo.
Security
- Auth error details are output-encoded with the
hepackage and served under a strict CSP (default-src 'none', no scripts) plusframe-ancestors 'none',X-Content-Type-Options: nosniff,Referrer-Policy: no-referrer, andCache-Control: no-store. The same hardening applies to the handle form.
Full changelog: #106
v0.4.0
Minor release adding the AT Protocol (Bluesky) authentication provider.
- New
atprotoprovider following the atproto OAuth profile (PKCE, DPoP-bound tokens, PAR). - Decentralized identity discovery with no hardcoded Bluesky/PDS hosts: handle → DID → DID document → PDS → authorization server. Works with
bsky.socialand self-hosted PDSes. - Public OAuth client (no secret); configured entirely through the
createStartupAPIfactory and enabled by the presence of theatprotoconfig key.
See the README "Bluesky / AT Protocol (atproto)" section for setup. (#102)
v0.3.2
Docs-only patch release: refreshes the README published to npm with the npm create startup-api scaffolder install path and automated-deployment guidance (Cloudflare Workers GitHub app / GitHub Actions). No code changes.
v0.3.1
Patch release.
- Power strip sits flush in the page corner (removed stray padding/border).
- Profile, accounts and admin pages now respect the user's color-scheme (light/dark) preference.
- Accent restyled to the lightning-bolt yellow (#ffcc00) with WCAG AA contrast across both themes.
v0.3.0 — Config-driven gate pages
Highlights
Config-driven "gate" pages (#460, #101)
A denied request can now serve an explainer page in place — at the requested URL, with no redirect — via the new on_unauthorized: 'gate' action. This generalizes the single-destination upgrade redirect and lets consumer projects delete hand-written worker wrappers in favor of configuration.
The served page varies by login state, and each variant's body is sourced from either the ASSETS binding (a local file) or a path proxied from ORIGIN_URL:
anonymous(required) — shown to logged-out visitors (e.g. "become a patron + log in").unentitled(optional) — shown to logged-in visitors who fail the requirement (e.g. "pledge/upgrade"); falls back toanonymouswhen omitted.status(optional) — HTTP status for the served page, default200.
Configure per rule via gate, or on the policy default via default_gate. The gate page is produced inside the deny path, so it is not re-subjected to the access policy and no power-strip is injected. No redirect means no loop risk.
accessPolicy: {
default: { mode: 'entitlement', provider: 'patreon', condition: { type: 'benefit', benefit_id: '...' } },
default_on_unauthorized: 'gate',
default_gate: {
anonymous: { origin: '/early-access' }, // or { asset: '/early-access' }
unentitled: { origin: '/pledge-needed' }, // or { asset: '/pledge-needed' }
},
}Fully backward compatible — all additions are optional, and existing forbidden/upgrade/login behavior is unchanged.
Full changelog: v0.2.0...v0.3.0