Client libraries for Altium 365 authentication (OAuth2/OIDC + PKCE, workspace token-exchange, refresh/revocation, and the Altium ActionWait desktop flow), built to a single language-neutral specification and held to one shared conformance suite.
The spec is the source of truth; each library is a hand-written, idiomatic implementation that is validated by the same vectors. Change the contract once, and every library's CI proves it still conforms.
spec/ Normative spec + JSON Schemas + conformance vectors (the source of truth)
SPEC.md The Altium delta over standard OAuth/OIDC
schemas/ JSON Schemas (token claims, ActionWait, token response, userinfo)
conformance/
vectors.json Language-neutral test vectors — every library runs these
README.md Vector format + matchers
docs/ Conceptual auth guides (language-neutral)
libs/
typescript/ @altium-developer/a365-auth
dotnet/ Altium.Auth
.github/workflows/ Per-library CI + release (path-filtered)
spec/ and docs/ are shared and language-neutral. Everything a given ecosystem
needs to build/test/publish lives under that library's libs/<lang>/ directory.
| Library | Package | Version | Status |
|---|---|---|---|
libs/typescript |
@altium-developer/a365-auth |
🧪 preview | |
libs/dotnet |
Altium.Auth |
not yet published | 🧪 preview |
The conceptual guides in docs/ and the specification are published as a
Material for MkDocs site at
https://altiumdeveloper.github.io/a365-auth/. The site is built from source in
CI (.github/workflows/docs.yml) — nothing generated is committed. Preview locally:
pip install -r requirements-docs.txt
mkdocs serveThe conformance vectors are the enforcement layer:
- One contract.
spec/conformance/vectors.jsondefines the expected request shapes and outcomes (authorize URL, token requests, ActionWait, revocation, …). - Every library runs them. Each
libs/<lang>has a conformance runner that reads the samevectors.jsonand asserts the same expectations:- TypeScript:
npm run test:conformance(inlibs/typescript) - .NET:
dotnet test libs/dotnet/tests/Altium.Auth.Tests
- TypeScript:
- CI gates on it. A change under
spec/**triggers every library's CI (path filter), so a contract change that desyncs any implementation fails in the same PR. A change underlibs/<lang>/**triggers only that library. - Atomic contract commits. Spec + vector + all affected libraries change in one reviewed PR.
Which shared vectors each library executes. live = behavioral reference that
needs a real server (skipped by offline runners in both).
| Vector group | TypeScript | .NET |
|---|---|---|
| authorizeUrl | ✅ | ✅ |
tokenRequest (exchange/workspace/refresh, Gov secure=1, cross-partition) |
✅ | ✅ |
| actionWait (200/408/410/non-JSON/missing-code/CSRF) | ✅ | ✅ |
revocation — revoke-refresh-token |
✅ | ✅ |
revocation — revoke-then-refresh-invalid-grant |
live | live |
| userinfo (response shape) | schema ref | schema ref |
| liveClaims (decoded token claims) | live | live |
- Spec is versioned (
spec/conformance/vectors.json→version). Each library declares which contract it targets; the spec CHANGELOG is the contract-change log. - Libraries version independently and publish from tag-prefixed releases:
ts-v*→ npm (.github/workflows/typescript-release.yml)dotnet-v*→ nuget.org (.github/workflows/dotnet-release.yml)
- Package
repository.directorymetadata points consumers at the right subdirectory.
libs/<lang>/with an idiomatic implementation of the spec.- A conformance runner that reads
spec/conformance/vectors.jsonand assertsexpectRequest/expectResult(see the TS/.NET runners as references). .github/workflows/<lang>-ci.yml(path-filtered onlibs/<lang>/**+spec/**) and a<lang>-release.yml.- Add rows to the tables above.
MIT — see LICENSE.