Skip to main content

caplinks

Capability links: hand someone a link to one thing, with no account. The token is the permission; a password may gate it; it expires; it can be revoked; password attempts are limited. Standard library only, no web framework.

pip install caplinks
from caplinks import CapabilityLinks

links = CapabilityLinks()  # records in a dict; pass any MutableMapping to persist them
rec = links.create({"doc": "report-1"}, password="open sesame", expires="7d")
url = f"https://example.com/s/{rec['token']}/"

state, stored = links.status(rec["token"])   # "ok", "expired" or "missing"
links.check_password(stored, "open sesame")  # True
cookie = links.unlock_value(stored)          # what a correct password earns
links.unlocked(stored, cookie, max_age_s=3600)  # True, until the password changes or the link is revoked
links.revoke(rec["token"])                   # now "missing"

What is in it

  • CapabilityLinks: create, read, list and revoke links, and gate them on a password. Records are plain dicts in any MutableMapping keyed by token: the generic fields are token, created, expires, password (a hash) and revoked; your own fields (what the link reaches) sit beside them.
  • ScryptHasher (stdlib scrypt) behind the PasswordHasher protocol (hash, verify -> bool): pass hasher= for argon2 or anything else.
  • parse_expires reads what people write (30m, 12h, 7d, 2w, 2026-11-01 meaning the end of that day UTC, an ISO timestamp, never) and refuses the past; is_expired fails closed.
  • SlidingWindowLimiter behind the RateLimiter protocol (allow(key) -> bool): count password attempts per client, per link, or both. It is per process; a shared limiter of the same shape (Redis, say) fits where several workers serve the links.

The unlock value is an HMAC keyed by the stored password hash, so changing the password or revoking the link (which clears the hash) ends every open session at once.

What stays with your app

What a link reaches (its scope), how it is served (routes, cookie name, headers), and the attempt policy. annals (share links) is the first host.

Seams

keyword default for
store dict persistence: a dol store, a file-backed mapping, S3
hasher ScryptHasher() argon2id or another scheme
clock now_utc tests that pin the time
min_password_len 8 a stricter or laxer gate

A store that cannot vouch for a record raises KeyError, ValueError or OSError when it is read, and the link is then missing; so is a record whose generic fields have the wrong types. Every failure closes the link.

Metadata

Release files for caplinks 0.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for caplinks 0.0.2
File Size Uploaded Provenance
caplinks-0.0.2.tar.gz 13.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for caplinks 0.0.2
File Interpreter ABI Platform
caplinks-0.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 25.1 kB

Security for caplinks 0.0.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page