Repository navigation
v3.4.0
Added
pandod server --multi-tenant(PANDO_MULTI_TENANT) for servers that strangers share:
internal repositories are for the owning organisation's members, members and grants must name
existing accounts, and any person may create up to--max-orgs-per-account(default 3)
organisations, in a namespace shared with logins and with service names reserved (ADR-032).- Browser sign-in for platform servers (
pandod server --login-listen): Google and any OpenID
Connect provider (--oidc ID=ISSUER), and single-use email links (--smtp-url,
--mail-from, optional Cloudflare Turnstile). A sign-in creates a 30-day platform token for
the console; first sign-ins create an account if--signupallows (default: a waitlist,
managed withpando admin signup allow|remove|list).pando admin identity linklets an
existing account, such as the first administrator, sign in from a browser (ADR-031).
Changed
- Looking up one organisation reads only that organisation.
Security
-
Protected branches: a change's author can no longer approve it through an agent they mint,
approve an agent's change they answer for, or report its required checks; such approvals don't
count (ADR-030). -
Single sign-on:
--oidc-require CLAIM=VALUEbinds tokens to your tenant, and pandod refuses to
start with GitHub Actions or Google as issuer without one. Tokens can't sign in as a platform
administrator (unless listed with--oidc-admin) or as anagent/orbot/account. Unknown
signing keys refetch the key set at most once a minute. -
Paths named
.gitor.pandoin any case, with trailing dots or spaces, as an NTFS stream or
as an 8.3 short name (GIT~1) are refused by the server, by checkouts and by imports, so a
writer can't plant git hooks or config in other people's checkouts. Existing history holding
such paths can no longer be read. -
Static tokens that are empty, shorter than 16 characters or a placeholder (
CHANGE-ME) are
refused at startup. -
Access answers are no longer re-cached from a read that raced a write, so a removed member or
grant loses access at once. -
pando migrate: the GitHub token comes fromPANDO_GITHUB_TOKEN(orGITHUB_TOKEN) or
--github-token-file;--github-tokenwarns that it is visible to other users. Source URLs
are printed without credentials, and the mirror clone goes to a private, randomly named
directory. -
Platform servers refuse repository calls that name no repository. Before, such a call reached
the server's own--metadatarepository with no access check, so any signed-in caller (or any
token, however limited) could read and write it. A non-UTF-8x-pando-repoheader is refused. -
Webhooks no longer call loopback, private networks (RFC 1918, 100.64.0.0/10, fc00::/7) or cloud
metadata (including 100.100.100.200, fd00:ec2::254 and IPv4 written as IPv6: mapped, NAT64,
6to4). Start with--webhook-allow-privateto let a self-hosted server call its internal
network (metadata stays refused). The address is checked when a webhook is saved and at every
delivery, deliveries connect only to the checked address (no DNS rebinding), DNS lookups time
out after 5 s, proxies from the environment are ignored, and a failed delivery or ping reports
only the HTTP status or "unreachable", never why.
Added
pandod backupsnapshots a platform server's registry and every repository's database to a
directory or object store while it runs;docs/deploy.mddocuments the restore.
Changed
- Docs: a platform server (
--platform) is single-node; only servers without it scale out. - Go SDK: requires Go 1.26.9 and uses
golang.org/x/net0.60.0 andgolang.org/x/text
0.42.0, fixing six known HTTP/2 and text-parsing vulnerabilities (GO-2026-6603, 6610, 6611,
6612, 6617, 6629). - Releases attach their signed SLSA provenance (
*.intoto.jsonl) next to the archives. - CI hardening: least-privilege workflow tokens, every action pinned to a commit, CodeQL on
every change, and Dependabot for Go, npm and Python as well as Rust and Actions.