Changelog

What we shipped, when, and why.

This page records LinkSilo's release history in human-readable language: what was added, what changed, what was removed, and which decisions reshaped the privacy posture. Pre-launch, a single entry documents the development snapshot that will form the v1 release. Post-launch, each release appends a dated entry at the top.

Last reviewed 2026-05-17

Conventions

What this changelog is, and what it isn't.

This changelog covers product-facing changes — features users interact with, architectural decisions that change what LinkSilo stores or doesn't store, and removals that close known foot-guns. It is hand-curated per release, not generated from commit history. Each release follows the Keep-a-Changelog convention: Added, Changed, Removed, Security.

The codebase-level history lives in our open-source monorepo on GitHub. Every line of LinkSilo's server and client code is open source and every change is publicly readable. The changelog here is the product-facing summary; the commits are the authoritative record. When a change has security implications worth pinning, the entry below cross-references the security and transparency pages where the underlying posture is documented.

0.1.0 — Pre-launch.

2026-04 → 2026-05 development arc

The first release of LinkSilo. Functionality scope is the v1 launch feature set per the launch plan; bug fixes and incremental refinements from the pre-launch hardening arc are folded into this entry rather than enumerated individually. Post-launch releases will track incremental changes against this baseline.

Added

Dashboard
Authenticated dashboard for creators: page editor with custom themes and link scheduling, real-time analytics (k-anonymized), tip-jar configuration, billing balance + recent transactions.
Public renderer
Read-only public page renderer at linksilo.io/p/<slug>. Connects to PostgreSQL under a SELECT-only role restricted to render-required columns; cannot read API keys, sessions, or admin tables.
Tiered plans
Free / Starter (€8) / Pro (€16) / Premium (€37) per month. Pages-per-account caps, analytics depth, custom domain support, and tip-jar fee percentages scale by tier. Premium tier ships 0% tip-jar fee.
Credit-ledger billing
Tier validity is funded by account-level credit-ledger balance. Manual top-up via Stripe Checkout (strict-unlinkability: customer=None, no persistent Stripe Customer record) or opt-in auto-top-up via Stripe Checkout setup mode. The daily debit cron draws per-tier cost from the balance.
Tip jar with Connect
Creators receive tips via Stripe Connect Express accounts. Visitor tip checkout uses destination charges with tier-aware platform fees (7% / 5% / 3% / 0%). Tip metadata sent to Stripe is opaque: a tip_code identifier only, no creator-identifying fields.
Newsletter capture
Pro+ feature. Subscriber emails sealed-box encrypted in the subscriber's browser. The server stores ciphertext plus an HMAC dedup hash; server-side dedup is possible, server-side decryption is not.
MFA + recovery
TOTP and WebAuthn / passkey step-up authentication. BIP-39 24-word recovery phrase generated at signup, displayed once, used as the sole recovery mechanism if the password is lost. Recovery does not bypass encryption — the phrase derives a key that decrypts the wrapped master key.
OIDC provider
silo-id acts as the OIDC provider for LinkSilo (PKCE-only, env-config client registry, Ed25519-signed ID tokens). The SvelteKit dashboard authenticates through this surface.
Account deletion (GDPR)
User-initiated erasure flow with email-verify token (7-day TTL), step-up AuthKey requirement, and cross-service cascade. Audit log entries about the deleted account are anonymized (account_id set to NULL) preserving forensic value while breaking the personal-data linkage GDPR requires us to remove.

Changed

Backend stack
Migrated from the original TypeScript/Node.js prototypes to Rust for security-critical services (silo-id, silo-billing, linksilo-render, linksilo-analytics-ingress) and Go for the linksilo-api product-glue layer. SvelteKit retained for browser frontends. The migration reduces the attack surface and pins a single TLS implementation (rustls-only TLS; no OpenSSL in the TLS path).
Billing model
Replaced the original Stripe Subscriptions model with a credit-ledger model: top-ups flow through one-shot PaymentIntents mediated by an allocation_code; tier validity is balance-driven by a daily debit cron with a grace-period state machine. The change improves payment-account decoupling (allocation_code rather than a one-time claim token) and avoids a class of recurring-charge edge cases.
Country determination at top-up
VAT MOSS country of the buyer is determined server-side at top-up time from Geo-IP and Accept-Language across five enumerated cases, rather than from a frontend-supplied hint. When Geo-IP and Accept-Language disagree the allocation_code is flagged for redemption-step user confirmation.
Auto-top-up disable surface
Disable now uses a single Stripe call (detach by saved payment_method_id) instead of the previous list-then-detach two-call sequence. The change shrinks LinkSilo's Stripe-side observability footprint on every disable.

Removed

Subscription-claim flow
The credit-ledger refactor replaced the Stripe Subscription model but initially left the old route handlers, webhook dispatch branches, and frontend client functions in place as half-state shim code. A subsequent change removed that residual surface end-to-end (3 routes, 4 service methods, 2 webhook dispatch branches, 6 environment price-ID variables, and the matching frontend client). The architectural replacement is the credit-ledger flow above under Changed -> Billing model.

Security

Browser-side crypto
XChaCha20-Poly1305-IETF AEAD, X25519 sealed-box, Ed25519 signatures, Argon2id (m=64MB, t=3, p=4), HMAC-SHA256, HKDF-SHA256. Implemented via the RustCrypto crate family compiled to WebAssembly. The server never holds plaintext for any data protected under these flows. Detailed claims and code-path mapping on the security page.
Never-recycle invariant
Aliases, usernames, page slugs, and recipient addresses tombstone forever via partial unique indexes. GDPR account deletion preserves slug tombstones (slug string only — no personally-identifying material) so a deleted creator's slug cannot be re-minted by a third party.
Atomic auto-top-up enable
The auto-top-up enable flow now flips the credit-ledger row only after Stripe confirms the saved-method capture (via the setup_intent.succeeded webhook). If the user closes the tab mid-setup, no DB state is written; previously a partially-completed setup could leave the ledger marked enabled with no working payment method, leading to a downgrade the user did not see coming.
Payment-claim decoupling
The link between a payment and the account that benefits from it is mediated through an allocation_code rather than a direct foreign key. A subpoena of the payment row alone does not produce the account it credited; both rows must be read together, and the bridging code is HMAC-hashed at rest.
Role-restricted database
PostgreSQL access is partitioned across roles: the renderer is read-only on a column-restricted view; the analytics ingress has no database access at all; the silo-billing service cannot write to silo-id tables and vice versa. A compromise of one service's database role cannot pivot to the others.
Logging discipline
Zero personally-identifying data in tracing! calls anywhere in the codebase. No recipient emails, no tokens, no key material, no payment-method identifiers. Audit logs use daily-rotated IP HMACs rather than IP addresses.
Cross-references

Where to find more.

Codebase history
Our open-source monorepo on GitHub. Every change is public; every commit lists its rationale.
Security posture
The security page documents the encryption, role separation, and transport hardening claims pinned in the Security section above.
Transparency report
The transparency page documents lawful-request counts, warrant canary, and per-flow Stripe linkage profile for the billing decisions pinned in the Changed section above.
Status
Operational status — uptime, incident history, scheduled maintenance — will live at status once LinkSilo opens to public traffic.