Birdigo.ShareLinks 2.1.0

Birdigo.ShareLinks

Stateless, self-contained shareable links. A URL is serialized, optionally DEFLATE-compressed, Base64Url-encoded and version-prefixed, then carried inside the link itself. The receiving app decodes it locally and navigates — no shortener service, no database, no resolve API, no network round-trip. The application is its own resolver.

Usage

using Birdigo;

string shareUrl = ShareableLink.Encode("https://app.birdigo.com/organizations/628/leads/300?section=Notes&noteId=1");
// https://app.birdigo.com/s/v1.AG9yZ2FuaXphdGlvbnMvNjI4L2xlYWRzLzMwMD9zZWN0aW9uPU5vdGVzJm5vdGVJZD0x

string url = ShareableLink.Decode(shareUrl);
// https://app.birdigo.com/organizations/628/leads/300?section=Notes&noteId=1

When the input is untrusted — user-supplied, stored, or off the wire — prefer the non-throwing pair:

if (ShareableLink.TryEncode(url, out string? shareUrl)) { /* share it */ }

string target = ShareableLink.TryDecode(shareUrl, out string? decoded)
    ? decoded!
    : "https://app.birdigo.com/dashboard";

That is the entire API: Encode, TryEncode, Decode, TryDecode, plus ShareLinkException to catch.

Any origin works

The origin is read from the URL you pass in and re-attached on the way out. Only the path, query and fragment travel inside the token.

ShareableLink.Encode("https://app.deltax.com/tenant/628/sales/300?company=Notes");
// https://app.deltax.com/s/v1.AHRlbmFudC82Mjgvc2FsZXMvMzAwP2NvbXBhbnk9Tm90ZXM

A staging link therefore decodes back to staging, and the same path on two hosts produces the same token. It also means the host in a share URL is attacker-controlled — never use it to select a tenant.

Behaviour worth knowing

Encode requires an absolute URL. A relative string like leads/300 throws ArgumentException rather than silently assuming an origin.

Round trips are equivalent, not byte-identical. Encode parses its input as a Uri, which normalises: a literal space becomes %20, https://app.birdigo.com gains a trailing slash, an uppercase host is lowercased, and an explicit :443 is dropped.

Compression is automatic. Long, repetitive URLs are DEFLATE-compressed; short ones are stored raw, because the block overhead would make them longer. A token is never larger than its uncompressed form. Nothing to configure.

ShareableLink is static, stateless and thread-safe. No DI registration needed.

Token format

{origin}/s/v1.<Base64Url(frame)>

The frame is a flags byte followed by the payload — raw UTF-8, or raw DEFLATE (RFC 1951) of it. Only bit 0x01 of the flags byte is defined; it marks a compressed payload. Reserved bits must be zero, and a token that sets one is rejected. Because the token records its own compression state, the decoder never has to guess.

The v1. prefix is what keeps old links alive. A future codec version ships behind a v2. prefix while v1 tokens keep resolving; the URL shape never changes.

Security

This is an encoding, not encryption. Anyone can read, edit or forge a token — leadId=300 becomes leadId=999 in one line. That is acceptable only because a token is a routing hint.

Never place access tokens, session ids, secrets, permission flags, or any user or tenant id you intend to trust inside a share link. No authorization decision may depend on token contents. Re-authorize the decoded destination server-side, exactly as if the user had typed that URL by hand — because they can.

Requirements

.NET 10. No dependencies beyond the base class library.

No packages depend on Birdigo.ShareLinks.

.NET 10.0

  • No dependencies.

Version Downloads Last updated
2.1.0 0 07/13/2026
2.0.0 0 07/13/2026
1.0.0 0 07/13/2026