Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 112 additions & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,120 @@ concurrency:
permissions:
contents: read

# Language matrix is path-gated on pull_request so a docs/i18n-only change does not spin up
# macos Swift builds or other native SDK scanners. push to main, weekly schedule, and manual
# dispatch still analyze every configured language.
jobs:
changes:
name: Detect languages
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
actions: ${{ steps.select.outputs.actions }}
javascript-typescript: ${{ steps.select.outputs.javascript-typescript }}
go: ${{ steps.select.outputs.go }}
python: ${{ steps.select.outputs.python }}
ruby: ${{ steps.select.outputs.ruby }}
java-kotlin: ${{ steps.select.outputs.java-kotlin }}
csharp: ${{ steps.select.outputs.csharp }}
swift: ${{ steps.select.outputs.swift }}
steps:
# actions/checkout v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 0

- name: Select languages to analyze
id: select
shell: bash
run: |
set -euo pipefail

enable_all() {
{
echo 'actions=true'
echo 'javascript-typescript=true'
echo 'go=true'
echo 'python=true'
echo 'ruby=true'
echo 'java-kotlin=true'
echo 'csharp=true'
echo 'swift=true'
} >> "$GITHUB_OUTPUT"
}

# Full matrix outside pull requests (main, schedule, workflow_dispatch).
if [[ "${{ github.event_name }}" != 'pull_request' ]]; then
enable_all
exit 0
fi

# PRs always scan workflow YAML and the TypeScript/JavaScript surface.
{
echo 'actions=true'
echo 'javascript-typescript=true'
} >> "$GITHUB_OUTPUT"

base='${{ github.event.pull_request.base.sha }}'
head='${{ github.event.pull_request.head.sha }}'
mapfile -t files < <(git diff --name-only "$base" "$head")

match() {
local re="$1"
local f
for f in "${files[@]}"; do
if [[ "$f" =~ $re ]]; then
return 0
fi
done
return 1
}

if match '^sdk/go/'; then echo 'go=true'; else echo 'go=false'; fi >> "$GITHUB_OUTPUT"
if match '^sdk/python/'; then echo 'python=true'; else echo 'python=false'; fi >> "$GITHUB_OUTPUT"
if match '^sdk/ruby/'; then echo 'ruby=true'; else echo 'ruby=false'; fi >> "$GITHUB_OUTPUT"
if match '^sdk/(java|android)/'; then
echo 'java-kotlin=true'
else
echo 'java-kotlin=false'
fi >> "$GITHUB_OUTPUT"
if match '^sdk/(dotnet|windows)/'; then
echo 'csharp=true'
else
echo 'csharp=false'
fi >> "$GITHUB_OUTPUT"
if match '^sdk/(ios|macos)/'; then
echo 'swift=true'
else
echo 'swift=false'
fi >> "$GITHUB_OUTPUT"

{
echo 'Selected CodeQL languages for this pull request:'
echo " actions=true"
echo " javascript-typescript=true"
echo " go=$(grep '^go=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)"
echo " python=$(grep '^python=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)"
echo " ruby=$(grep '^ruby=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)"
echo " java-kotlin=$(grep '^java-kotlin=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)"
echo " csharp=$(grep '^csharp=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)"
echo " swift=$(grep '^swift=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)"
}

analyze:
name: Analyze ${{ matrix.language }}
if: github.event.repository.visibility == 'public'
needs: changes
if: |
github.event.repository.visibility == 'public' && (
(matrix.language == 'actions' && needs.changes.outputs.actions == 'true') ||
(matrix.language == 'javascript-typescript' && needs.changes.outputs.javascript-typescript == 'true') ||
(matrix.language == 'go' && needs.changes.outputs.go == 'true') ||
(matrix.language == 'python' && needs.changes.outputs.python == 'true') ||
(matrix.language == 'ruby' && needs.changes.outputs.ruby == 'true') ||
(matrix.language == 'java-kotlin' && needs.changes.outputs.java-kotlin == 'true') ||
(matrix.language == 'csharp' && needs.changes.outputs.csharp == 'true') ||
(matrix.language == 'swift' && needs.changes.outputs.swift == 'true')
)
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
permissions:
Expand Down Expand Up @@ -54,6 +164,7 @@ jobs:
build-mode: manual
runner: macos-latest
steps:
# actions/checkout v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1

- name: Initialize CodeQL
Expand Down
37 changes: 35 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,53 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/), and this
project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).

The repository has no release tags yet. The root `package.json` version is `0.0.0`. Until a `0.x`
tag is published, `main` is the only reference point and the public API is unstable.
## Versioning

| Situation | Identifier |
| --------- | ---------- |
| Pre-release development on `main` | Git **commit SHA** (unique per revision). Root `package.json` remains `0.0.0` until the first tagged release. |
| Published release | Annotated git tag `vMAJOR.MINOR.PATCH` (SemVer), matching a GitHub Release and a CHANGELOG section. |
| Public API stability | Unstable until 1.0.0; breaking changes may land without a long deprecation window while pre-1.0. |

When a release is cut: add a dated `## [X.Y.Z] - YYYY-MM-DD` section, move items out of
`[Unreleased]`, and tag the repository. Every published release is identified in version control by
that tag.

### Security entries

Every **publicly known** vulnerability fixed in a release **must** be listed under a `### Security`
heading in that release’s notes (CVE or advisory URL when available). If a release has no security
fixes, omit the heading. Private reports that never became public need not be listed until
disclosure.

OpenSSF Best Practices self-certification notes: [`docs/openssf-best-practices.md`](docs/openssf-best-practices.md).

## [Unreleased]

### Security

- No publicly disclosed vulnerability fixes in this period.
- Documented OpenSSF-aligned fix timelines (60-day public medium+ fixes, critical prioritization),
cryptography defaults, and static/dynamic analysis practices in `SECURITY.md`.

### Changed

- **License changed from Elastic License 2.0 to the MIT License.** XID is now open source under an
OSI-approved license. The Elastic License restrictions (no hosted service offering, no license key
circumvention, no removal of license notices) no longer apply. The only remaining obligation is to
retain the copyright and permission notice.
- Clarified versioning (commit SHA until first SemVer tag) and Security release-note rules in
`CHANGELOG.md`.
- Homepage footer and README community tables now link Support, Security, and Contributing for
feedback and contribution discovery.

### Added

- OpenSSF Best Practices Passing self-certification pack:
[`docs/openssf-best-practices.md`](docs/openssf-best-practices.md) with paste-ready Met/N/A
justifications for project 13783.
- Explicit Testing policy and warnings/static-analysis section in `CONTRIBUTING.md`.

- Enterprise org structure (OrgUnit): an in-org business tree with adjacency plus materialized path
(depth cap 8), primary/secondary post placement, reporting-line manager resolution walking up the
ancestor chain, and nine Management API endpoints under `/v1/organizations/:orgId/units` (tree
Expand Down
40 changes: 36 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,24 @@ Reuse the existing kernel packages instead of reimplementing: `@xid-kit/crypto`
hashing, `@xid-kit/protocol` for OIDC/OAuth logic, `@xid-kit/webauthn` for assertion verification,
`@xid-kit/saml` for SAML.

## Tests
## Testing policy

Vitest, files named `<name>.test.ts` next to the code under test. Arrange, Act, Assert, separated by
blank lines. Test names describe the scenario and expectation, for example
`it('rejects PKCE plain challenge', ...)`.
When a **major new feature** is added to software this project produces, automated tests for that
feature **must** be added in the same change set (or an immediately following commit in the same
pull request). This is a standing project policy, not optional guidance.

Vitest is the FLOSS automated test suite for TypeScript packages and apps. Files are named
`<name>.test.ts` next to the code under test. Arrange, Act, Assert, separated by blank lines. Test
names describe the scenario and expectation, for example `it('rejects PKCE plain challenge', ...)`.

Invoke tests the standard way:

```bash
pnpm test # turbo run test (Vitest across the workspace)
pnpm run check # full gate including coverage and protocol gates
```

CI runs these on every pull request and on pushes to `main` (see `.github/workflows/ci.yml`).

A pull request **must** include tests when it touches:

Expand All @@ -262,6 +275,25 @@ Prefer boundary and failure paths: empty input, oversized input, expired tokens,
`sign_count`, malformed external IdP responses. Do not write tests for placeholders, pure types, or
third-party library behavior.

The pull request template repeats this policy under its checklist so reviewers can verify that tests
were considered. Evidence that the policy is followed appears in co-located `*.test.ts` files and
repository-level gates under `tests/`.

## Warnings, lint, and static analysis

Quality gates (not optional for merge):

| Tool | Role | How it runs |
| ---- | ---- | ----------- |
| Oxlint + Oxfmt | Lint and format (warnings treated as CI failures where configured as errors) | `pnpm run check` / `pnpm run lint` |
| TypeScript `tsc --noEmit` | Strict typecheck | `pnpm run typecheck` via turbo in `pnpm run check` |
| CodeQL | Static analysis for common vulnerability classes | `.github/workflows/codeql.yml` on PR, push to `main`, weekly cron |
| `pnpm audit` | Production dependency advisories | `pnpm run security:dependencies` |
| Secret scan script | Repo secret leak check | `pnpm run security:secret-scan` |

Do not disable lint or type rules to hide a defect. Fix the root cause or, for a true false positive,
narrow the exception with a documented reason next to the config change.

## Commits and pull requests

Commit messages follow [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/):
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,17 @@ guides exist in English only, because a stale translation of a support matrix is

## Contributing, security, and license

Read [`CONTRIBUTING.md`](CONTRIBUTING.md) before opening a pull request; it covers the toolchain,
the required gates, and the Developer Certificate of Origin sign-off. Participation is governed by
[`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md), and [`SUPPORT.md`](SUPPORT.md) covers questions that
are not code changes. Do not open a public issue for a vulnerability -- reporting channels, scope,
and the disclosure timeline are in [`SECURITY.md`](SECURITY.md).
| Topic | Where |
| ----- | ----- |
| How to contribute (PR flow, DCO, testing policy, coding standards) | [`CONTRIBUTING.md`](CONTRIBUTING.md) |
| Bug reports, feature requests, questions | [`SUPPORT.md`](SUPPORT.md) · [Issues](https://github.com/StringKe/xid/issues) · [Discussions](https://github.com/StringKe/xid/discussions) |
| Vulnerability reports (private only) | [`SECURITY.md`](SECURITY.md) |
| Code of conduct | [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) |
| OpenSSF Best Practices (Passing) checklist and form answers | [`docs/openssf-best-practices.md`](docs/openssf-best-practices.md) |
| License | [`LICENSE`](LICENSE) (MIT) |

Do not open a public issue for a vulnerability. Reporting channels, scope, fix timelines, and the
cryptography summary are in [`SECURITY.md`](SECURITY.md).

XID is licensed under the MIT License; see [`LICENSE`](LICENSE). You may use, modify, and
distribute it, including commercially and in closed-source products, as long as you retain the
Expand Down
14 changes: 10 additions & 4 deletions README.zh-Hans.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,16 @@ release 声明。

## 贡献、安全与许可

提交 pull request 前请先阅读 [`CONTRIBUTING.md`](CONTRIBUTING.md),其中涵盖工具链、必过关卡与 Developer
Certificate of Origin 签署。参与行为受 [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) 约束,
[`SUPPORT.md`](SUPPORT.md) 覆盖代码变更之外的提问渠道。发现漏洞请勿开公开 issue:报告渠道、范围与披露
时间线见 [`SECURITY.md`](SECURITY.md)。
| 主题 | 位置 |
| ---- | ---- |
| 如何贡献(PR 流程、DCO、测试策略、编码规范) | [`CONTRIBUTING.md`](CONTRIBUTING.md) |
| Bug / 功能请求 / 提问 | [`SUPPORT.md`](SUPPORT.md) · [Issues](https://github.com/StringKe/xid/issues) · [Discussions](https://github.com/StringKe/xid/discussions) |
| 漏洞报告(仅私密渠道) | [`SECURITY.md`](SECURITY.md) |
| 行为准则 | [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) |
| OpenSSF Best Practices(Passing)清单与表单答案 | [`docs/openssf-best-practices.md`](docs/openssf-best-practices.md) |
| 许可 | [`LICENSE`](LICENSE)(MIT) |

发现漏洞请勿开公开 issue。报告渠道、范围、修复时限与密码学摘要见 [`SECURITY.md`](SECURITY.md)。

XID 以 MIT License 授权,见 [`LICENSE`](LICENSE)。你可以使用、修改和分发它,包括商业用途和闭源产品,
只要保留版权声明与许可证文本。
37 changes: 37 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,43 @@ window collapses to whatever is needed to ship a fix.

Reporters are credited in the published advisory unless they ask not to be. There is no bug bounty.

## Fix timelines

These targets align with OpenSSF Best Practices (Passing) expectations:

| Class | Target |
| ----- | ------ |
| Acknowledgement of a private report | 5 business days (badge maximum 14 days) |
| Medium or higher severity vulnerability that is **publicly known** | Fixed and available on `main` within **60 days** of public knowledge |
| Critical severity after private report | Prioritized for the fastest practical fix; timeline shared after assessment |
| Publicly disclosed fixed vulnerability | Listed under a `### Security` section in [`CHANGELOG.md`](CHANGELOG.md) when the fix ships |

Public knowledge means a published CVE/NVD entry, or the project publishes the issue. Severity for the 60-day rule follows CVSS 2.0 base score ≥ 4 (medium or higher), consistent with the badge criterion.

There are no long-term support branches. The fix lands on `main`; consumers track `main` or rebase onto it.

## Cryptography

XID is identity infrastructure and uses cryptography heavily. Defaults:

| Area | Practice |
| ---- | -------- |
| Primitives | Platform **Web Crypto** (`crypto.subtle`, `crypto.getRandomValues`) only. Application code does not implement AES, RSA, ECDSA, SHA, HKDF, or random generators. |
| Password hashing | **Argon2id** via `@noble/hashes`, unique per-user salt, server-side pepper in Workers Secrets (never in D1). |
| Token signing | Instance **ES256** (P-256) keys; private keys envelope-encrypted with **AES-256-GCM** under a KEK in Workers Secrets. Plaintext private keys are never persisted. |
| Hashing for integrity | SHA-256 (audit chain, digests). Not MD5/SHA-1 for security. |
| Transport | HTTPS/TLS at the edge (Cloudflare). No http distribution of the project site or repository. |
| Forbidden for secrets | `Math.random`, home-grown crypto, storing password or reset secrets in plaintext. |

Design detail: `docs/design/00-overview.md` (build-vs-buy and signing keys). Contributor rules: crypto boundary in project AI standards and `CONTRIBUTING.md`.

## Static and dynamic analysis

- **Static analysis:** GitHub CodeQL on pull requests, pushes to `main`, and a weekly schedule (`.github/workflows/codeql.yml`). Confirmed medium/high exploitable findings are fixed promptly.
- **Dependency review:** Dependabot and dependency-review workflow on pull requests.
- **Secret scanning:** GitHub secret scanning and push protection, plus `pnpm run security:secret-scan`.
- **Dynamic analysis:** Vitest unit/integration suites and Workers smoke tests exercise protocol and auth paths with varied inputs (`pnpm test`, CI).

## In scope

Vulnerabilities in the code in this repository, in particular:
Expand Down
23 changes: 14 additions & 9 deletions SUPPORT.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Support

XID is maintained as an open source project. Community support is best-effort with no service level
agreement.
agreement. This file is the project’s public map for **how to get help, report bugs, request
enhancements, and contribute**.

## Where to go

| Need | Channel |
| --------------------------------------- | ---------------------------------------------------------------------- |
| Security vulnerability | [`SECURITY.md`](SECURITY.md). Never a public issue. |
| Bug report | [Issues](https://github.com/StringKe/xid/issues) with the bug template |
| Protocol or specification conformance | Issues, protocol conformance template |
| Feature request | Issues, feature request template |
| Question, integration help, design idea | [Discussions](https://github.com/StringKe/xid/discussions) |
| Contributing a change | [`CONTRIBUTING.md`](CONTRIBUTING.md) |
| Need | Channel |
| --------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Security vulnerability | [`SECURITY.md`](SECURITY.md). **Never** a public issue. Prefer GitHub private vulnerability reporting. |
| Bug report | [New issue](https://github.com/StringKe/xid/issues/new/choose) using the **bug** template |
| Protocol or specification conformance | Issues, **protocol conformance** template |
| Feature / enhancement request | Issues, **feature request** template, or [Discussions](https://github.com/StringKe/xid/discussions) |
| Question, integration help, design idea | [Discussions](https://github.com/StringKe/xid/discussions) |
| Contributing a change | [`CONTRIBUTING.md`](CONTRIBUTING.md) (pull requests + DCO) |
| Code of conduct | [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) |

Public issue and discussion history is the searchable archive of reports and replies:
https://github.com/StringKe/xid/issues

## Before opening an issue

Expand Down
Loading