mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-27 08:12:22 +01:00
Merge current dev and refresh PR #6739 from the 7011 integration
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
# Odysseus maintainer handbook
|
||||
|
||||
Odysseus maintainers are trusted to act, not to wait for permission. The default is individual responsibility; additional review is required when the **risk** warrants it.
|
||||
|
||||
This handbook records the project's maintainer governance and gives reviewers a reusable process. It complements [CONTRIBUTING.md](../../CONTRIBUTING.md) and [SECURITY.md](../../SECURITY.md); it does not replace the PR template, repository protections, or product decisions.
|
||||
|
||||
## At a glance
|
||||
|
||||
| Area | Working rule |
|
||||
|---|---|
|
||||
| Product direction | Pewds is the Product Owner |
|
||||
| Ordinary, reversible maintainer PR | Self-merge allowed after appropriate validation and applicable repository checks |
|
||||
| External contribution | Maintainer review required |
|
||||
| High-risk change | At least one **independent, qualified** maintainer review |
|
||||
| Access | Need-to-have, least privilege, separately granted per system |
|
||||
| Release | A designated Release Maintainer owns preparation and publish |
|
||||
| Inactivity | Access review after 2 months without activity, notice, or response |
|
||||
| Documentation | Repository Markdown is canonical |
|
||||
|
||||
These are governance rules, not guarantees that a GitHub permission or branch-protection setting permits a particular action. Respect the stronger applicable automated gate.
|
||||
|
||||
## Start here
|
||||
|
||||
- [Roles and access](roles-and-access.md): responsibility, permissions, and continuity.
|
||||
- [Product and feature proposals](product-and-features.md): product approval versus technical ownership.
|
||||
- [Changes and review](changes-and-review.md): review thresholds, self-merge, contributor corrections.
|
||||
- [Practical review playbook](review-playbook.md): risk, provenance, CI, CodeQL, independent audit, and handoff evidence.
|
||||
- [Triage](triage.md): turning incoming reports into actionable work.
|
||||
- [Testing and releases](testing-and-releases.md): evidence, platform validation, promotion to main.
|
||||
- [Documentation](documentation.md): canonical sources, updates, and traceability.
|
||||
|
||||
## Accountability
|
||||
|
||||
Maintainers own the changes they take on, including validation, regression prevention, follow-up, and rollback when needed. Roles describe responsibilities, not a hierarchy of technical approval.
|
||||
|
||||
Important product-direction decisions go through the Product Owner. Maintainers retain responsibility for feasibility, implementation, maintainability, and security.
|
||||
|
||||
AI coding or review agents can help collect evidence, test hypotheses, and prepare changes, but they are not the qualified human reviewer required for high-risk changes. A maintainer must inspect and accept the evidence.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Changes and review
|
||||
|
||||
Review is **risk-based**. Trusted maintainers should be able to ship ordinary work without creating a queue of ceremonial approvals.
|
||||
|
||||
## Required review
|
||||
|
||||
| Change | Minimum review rule |
|
||||
|---|---|
|
||||
| Ordinary, reversible maintainer change | Independent approval optional; self-merge permitted after appropriate validation |
|
||||
| External contribution | Maintainer review required |
|
||||
| High-risk change | At least one independent, qualified maintainer review required |
|
||||
|
||||
Repository branch protection and required checks also apply. Never treat this document as permission to bypass a live protection rule.
|
||||
|
||||
## Ordinary maintainer changes
|
||||
|
||||
1. Open a PR against `dev`, scoped to one coherent change.
|
||||
2. Explain intent, expected behavior, validation, and rollback if relevant.
|
||||
3. Run suitable tests and inspect the actual result.
|
||||
4. Ensure applicable required checks pass, address feedback, and merge when ready.
|
||||
|
||||
Self-merge is allowed for ordinary reversible work. The author remains responsible for follow-up, correction, and rollback.
|
||||
|
||||
## External contributions and small corrections
|
||||
|
||||
External contributions receive maintainer review.
|
||||
|
||||
A maintainer may directly fix a **small, obvious** problem in a contributor PR when the intended behavior is clear and the repair is faster than a separate round trip. Document what changed, preserve contributor attribution and history, avoid force-pushing, and re-run affected checks.
|
||||
|
||||
Substantive or ambiguous corrections require discussion with the contributor or a separately scoped correction. A maintainer must not silently turn a contributor's PR into unrelated work. Any corrective commit changes the SHA being reviewed; update validation and audit evidence accordingly.
|
||||
|
||||
## High-risk changes
|
||||
|
||||
High-risk work requires **at least one independent qualified review**. The author cannot be the only approver. Examples:
|
||||
|
||||
- Authentication, authorization, tenancy, sandboxing, agent tool permissions, or secrets.
|
||||
- Outbound network and SSRF defenses, sensitive integrations, and deployment access.
|
||||
- Destructive operations, deletion, filesystem ownership, and data migrations.
|
||||
- Persistence and concurrency invariants with possible data loss.
|
||||
- Major architectural contracts, release infrastructure, or changes hard to roll back.
|
||||
|
||||
A high-risk review should verify the threat or failure model, exact final commit, reproducer or regression evidence, failure and rollback behavior, and the relevant CI/security findings. Use the [review playbook](review-playbook.md).
|
||||
|
||||
## Cross-area changes and CODEOWNERS
|
||||
|
||||
Touching multiple areas does **not** automatically require multiple approvals. Consult domain expertise when needed. `.github/CODEOWNERS` currently contains no ownership rules; the per-area map is under discussion in [issue #593](https://github.com/odysseus-dev/odysseus/issues/593). Once populated, it helps identify reviewers and accountable contacts; it is not a blanket approval requirement by itself.
|
||||
|
||||
## Validation and UI evidence
|
||||
|
||||
Automated tests count as runtime evidence when they truly exercise the changed behavior. Use manual validation when coverage is insufficient.
|
||||
|
||||
For any change to visible UI behavior, follow the current [contributor UI checklist](../../CONTRIBUTING.md#style-and-visual-changes) and the repository PR template. Screenshots or clips are expected when they materially demonstrate the rendered result; screenshots alone do not replace behavioral tests.
|
||||
|
||||
## Disagreement and escalation
|
||||
|
||||
The maintainer doing the work owns ordinary implementation decisions within approved product direction and existing technical contracts. For substantive disagreements:
|
||||
|
||||
1. Involve a qualified maintainer with relevant expertise.
|
||||
2. Escalate unresolved cross-cutting technical issues to trusted project-wide maintainers.
|
||||
3. Refer product-direction disagreements to the Product Owner.
|
||||
|
||||
Security findings should be handled via [SECURITY.md](../../SECURITY.md), without disclosing exploit details in public issues. Repository protection rules should support these risk-based policies and should not accidentally force independent approval for every ordinary maintainer PR.
|
||||
@@ -0,0 +1,32 @@
|
||||
# Documentation
|
||||
|
||||
Repository Markdown is the canonical source for project documentation. A public docs site may be generated from it; avoid maintaining an independent wiki copy unless there is a deliberate future decision to do so.
|
||||
|
||||
## Where information belongs
|
||||
|
||||
| Location | Purpose |
|
||||
|---|---|
|
||||
| `/design` | Product intent, proposals, and accepted decisions (when those paths are used) |
|
||||
| `/specs` | Technical contracts and invariants |
|
||||
| `/website` | User, setup, configuration, and deployment guidance (published as the docs site) |
|
||||
| `/docs` | Developer, architecture, security, and maintainer guidance |
|
||||
| Root Markdown | Discoverable entry points and policies |
|
||||
|
||||
Keep root documents easy to find:
|
||||
|
||||
- `README.md`
|
||||
- `CONTRIBUTING.md`
|
||||
- `SECURITY.md`
|
||||
- `THREAT_MODEL.md`
|
||||
|
||||
Not every named directory exists today; do not invent a parallel documentation store just to match this map.
|
||||
|
||||
## Updating documentation
|
||||
|
||||
When behavior, architecture, a workflow, or its verification requirements change, update the canonical documentation in the same PR when appropriate.
|
||||
|
||||
Separate **policy** from **examples**: examples may evolve with tooling; changes to role authority, review requirements, or product ownership require an explicit governance decision. Do not introduce a new mandatory approval rule through a checklist alone.
|
||||
|
||||
Documentation PRs should link the relevant issue, record what was reviewed (links, commands, or affected features), and avoid publishing private channels, account names, local paths, secrets, or confidential incident details.
|
||||
|
||||
For practical examples of review evidence, see the [review playbook](review-playbook.md). For contributor setup and PR requirements, use [CONTRIBUTING.md](../../CONTRIBUTING.md).
|
||||
@@ -0,0 +1,48 @@
|
||||
# Product and feature proposals
|
||||
|
||||
Pewds ([@pewdiepie-archdaemon](https://github.com/pewdiepie-archdaemon)) is the Product Owner for Odysseus and has final authority over product direction. Maintainers own technical feasibility, implementation, and safety.
|
||||
|
||||
## Which changes require product approval?
|
||||
|
||||
**Product Owner approval before implementation:** substantial new features, changes to product direction, and product changes that are hard to reverse.
|
||||
|
||||
**No separate product approval by default:** bug fixes, security fixes, maintenance, tests, CI, documentation, internal refactors, and small, reversible product changes within existing direction.
|
||||
|
||||
Maintainers may make those smaller product decisions. Pewds can ask for changes or a rollback; the maintainer owns safe rollback or recovery.
|
||||
|
||||
### Urgent security and reliability fixes
|
||||
|
||||
Urgent fixes or containment may proceed without prior product approval, even if behavior temporarily changes. Keep the change to what stops the immediate problem, notify Pewds promptly, and record the reason and rollback or recovery plan. Agree on any lasting product-direction change with Pewds afterwards. Normal high-risk review and repository checks still apply.
|
||||
|
||||
## Product Owner initiated
|
||||
|
||||
```text
|
||||
Product Owner proposal or implementation
|
||||
-> technical feasibility
|
||||
-> plan and implementation
|
||||
-> risk-based review and validation
|
||||
```
|
||||
|
||||
A Product Owner proposal is already product-approved; it is not automatically technically approved or exempt from high-risk review.
|
||||
|
||||
## Community or maintainer initiated
|
||||
|
||||
Community proposals start as a Feature Request issue. Check [ROADMAP.md](../../ROADMAP.md) and existing issues first; take early ideas to [Discussions](https://github.com/odysseus-dev/odysseus/discussions/categories/ideas).
|
||||
|
||||
```text
|
||||
Feature proposal
|
||||
-> Product Owner accepts / rejects, where approval is required
|
||||
-> technical feasibility
|
||||
-> plan and implementation
|
||||
-> risk-based review and validation
|
||||
```
|
||||
|
||||
Record the decision in an issue, proposal, work item, or PR so future maintainers can discover it. Do not rely on a chat-only decision.
|
||||
|
||||
## Decision boundaries
|
||||
|
||||
The Product Owner decides **what belongs in Odysseus**. Maintainers decide **how approved work is built safely and maintainably**.
|
||||
|
||||
A rejected or out-of-scope feature can be maintained independently in a contributor's fork.
|
||||
|
||||
If the Product Owner is unavailable, work requiring prior product approval waits unless authority was explicitly delegated. Smaller decisions and urgent fixes follow the rules above.
|
||||
@@ -0,0 +1,129 @@
|
||||
# Practical PR review playbook
|
||||
|
||||
Use this as a **repeatable review method**, not as an extra organizational approval ladder. The binding minimums remain in [changes and review](changes-and-review.md): ordinary maintainer changes may be self-merged, external PRs require maintainer review, and high-risk work requires at least one independent qualified maintainer review.
|
||||
|
||||
No single checklist replaces engineering judgment. Increase depth with risk.
|
||||
|
||||
## 1. Understand the PR and establish its review gates
|
||||
|
||||
- Establish the problem, what the PR fundamentally proposes, and why the approach makes sense.
|
||||
- Check product direction, architecture fit, and scope before detailed review.
|
||||
- Write down the questions the review must answer, the evidence needed, and what would block further review or approval.
|
||||
- Confirm repository, source fork, target branch (`dev`), exact **HEAD SHA**, and current base.
|
||||
- Review the full effective diff, commit history, issue, prior feedback, and related upstream changes.
|
||||
- Confirm the branch is mergeable against the **current** `dev`, not an older local snapshot.
|
||||
- Identify the user-facing contract, affected data and users, security boundaries, and rollback plan.
|
||||
- Separate pre-existing upstream problems from regressions introduced or made reachable by the PR.
|
||||
|
||||
Example read-only commands:
|
||||
|
||||
```bash
|
||||
REPO="odysseus-dev/odysseus"
|
||||
PR=1234
|
||||
gh pr view "$PR" --repo "$REPO" --json title,state,isDraft,headRefOid,baseRefName,mergeable
|
||||
gh pr diff "$PR" --repo "$REPO"
|
||||
gh pr checks "$PR" --repo "$REPO"
|
||||
```
|
||||
|
||||
A green check on an old commit does not verify the revised branch.
|
||||
|
||||
## 2. Review the failure and threat model
|
||||
|
||||
For the relevant change, ask what happens with malformed input, missing auth state, wrong owner, concurrent requests, stale caches, partial failure, retries, cancelled jobs, unavailable dependencies, and restart/recovery.
|
||||
|
||||
Prioritize boundaries that can lose data or authority: identity, delegated API tokens, filesystem confinement, email deletion, persistence versioning, network/SSRF destinations, secrets, and agent tool execution.
|
||||
|
||||
For security claims, demonstrate the source-to-sink path and the *actual* guard. Tests must represent production middleware or transport where a unit mock could conceal a bypass.
|
||||
|
||||
## 3. Correct without obscuring contributor work
|
||||
|
||||
For small, unambiguous issues, maintainers may add focused corrections directly to a contributor PR under [the contribution review policy](changes-and-review.md#external-contributions-and-small-corrections). Preserve provenance, explain the change, prefer normal commits and fast-forward pushes, and avoid unrelated rewrites.
|
||||
|
||||
For substantive or ambiguous work, ask the contributor or prepare a clearly separated patch. Any code change means validating **the new SHA**, not approving based solely on the previous audit.
|
||||
|
||||
## 4. Build an evidence record
|
||||
|
||||
Run contributor code under the [runtime isolation rules](testing-and-releases.md#runtime-isolation).
|
||||
|
||||
Useful evidence includes:
|
||||
|
||||
- Pre-fix reproduction, expected outcome, and actual outcome.
|
||||
- Focused regression tests for the fix and broad suites relevant to cross-cutting effects.
|
||||
- Actual runtime checks (browser/UI, backend, Docker, supported OS) where necessary.
|
||||
- Exact executed commands, result counts, skipped cases, and environmental limitations.
|
||||
- GitHub required checks and conflict-free state on the exact final SHA.
|
||||
- Relevant operational consequences (data migration, rollback, compatibility).
|
||||
|
||||
Keep audits reproducible. A screenshot alone is not a functional test, and a passing mocked test is not proof that a production integration path is safe.
|
||||
|
||||
## 5. Independent review for high-risk changes
|
||||
|
||||
A separate **qualified maintainer** must inspect high-risk changes; the implementing author cannot be the sole reviewer. Independent coding agents may be useful for adversarial tests and cross-checks, but **an AI agent is not itself a GitHub approver** and does not replace human accountability.
|
||||
|
||||
To avoid confirmation bias, give the independent reviewer the current SHA, changed files, acceptance criteria, known reproduction, and explicit permission to challenge the proposed solution. Preserve unresolved findings and require a new audit when meaningful fixes change the diff.
|
||||
|
||||
## CodeQL and security scanning
|
||||
|
||||
A successful CodeQL workflow means analysis ran, not that the security dashboard is empty. Likewise, resolving a PR discussion does not necessarily resolve its code-scanning alert.
|
||||
|
||||
For each relevant alert:
|
||||
|
||||
1. Record the alert number, rule, severity, file/line, state, and source-to-sink trace if applicable.
|
||||
2. Compare with the current `dev` baseline; decide whether the PR introduced, exposed, or did not affect it.
|
||||
3. Reproduce or reason through the actual production behavior, including validation and authorization.
|
||||
4. **Fix** credible vulnerabilities, preferably with a regression test. Do not hide them by broad suppressions.
|
||||
5. **Recommend dismissal** only for a demonstrable false positive or a stale/invalid finding, with a precise technical explanation; only authorized maintainers should dismiss alerts.
|
||||
6. Document genuine but intentionally accepted risk separately. A true positive is not a false positive merely because it is deliberate.
|
||||
7. Rerun or inspect updated analysis on the final commit and confirm no blocking issues remain.
|
||||
|
||||
Never publish exploit payloads, secrets, or credentials in public review comments. See [SECURITY.md](../../SECURITY.md).
|
||||
|
||||
## 6. Decide and integrate
|
||||
|
||||
Before approval or self-merge, verify:
|
||||
|
||||
- Current branch and reviewed SHA are still the ones to be merged.
|
||||
- All applicable required checks are complete and successful.
|
||||
- High-risk independent review is present, where required.
|
||||
- No unresolved, credible P0/P1/P2 security or data-integrity defects remain in the change. Resolve or explicitly document P3 observations with a tracked owner and priority.
|
||||
- Review discussions, compatibility risks, and operational handoffs have been addressed.
|
||||
- The correct target is `dev`; `main` is curated for releases.
|
||||
|
||||
This P0-P3 classification is [triage guidance](triage.md#practical-priority-language), not a replacement for branch protection or an excuse to self-approve high-risk work. Maintainers may apply a stricter bar where warranted.
|
||||
|
||||
For a final manual merge, GitHub CLI supports an exact-head guard:
|
||||
|
||||
```bash
|
||||
gh pr merge 1234 --repo odysseus-dev/odysseus --squash \
|
||||
--match-head-commit <reviewed-full-head-sha>
|
||||
```
|
||||
|
||||
Use `--delete-branch` only when removing the source branch is appropriate and does not disrupt another workstream. Do not force a merge past review or security requirements.
|
||||
|
||||
## 7. Post-merge follow-up
|
||||
|
||||
Verify the PR actually merged and reference its integration commit. Record remaining operational work, such as schema migrations, backup/restore verification, service restarts, or compatibility documentation. A code change to a container mount does **not** by itself migrate existing runtime data.
|
||||
|
||||
Do not silently mark a deferred data migration complete; track its owner, evidence, rollback, and execution separately.
|
||||
|
||||
## Reusable reviewer handoff
|
||||
|
||||
```text
|
||||
PR / target:
|
||||
Reviewed source HEAD SHA:
|
||||
Current target branch SHA:
|
||||
Scope and changed files:
|
||||
Impact and risk classification:
|
||||
Security / correctness invariants challenged:
|
||||
Pre-fix reproducer and post-fix evidence:
|
||||
Tests run, skipped, and environment:
|
||||
CodeQL / scanning alert dispositions:
|
||||
Required GitHub checks (exact SHA):
|
||||
Mergeability and remaining conflicts:
|
||||
Unresolved P0 / P1 / P2 / P3 findings:
|
||||
Rollback / operational follow-ups:
|
||||
Independent qualified review required? Completed?
|
||||
Verdict: APPROVED / CHANGES REQUIRED / BLOCKED
|
||||
```
|
||||
|
||||
State what was actually verified. Do not write "all checks green" if only a subset of workflows was inspected.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Roles and access
|
||||
|
||||
Roles clarify who is accountable. They do not create a management chain or automatically grant privileges.
|
||||
|
||||
## Responsibility and typical access
|
||||
|
||||
| Responsibility | Typical GitHub access | Purpose |
|
||||
|---|---|---|
|
||||
| Product Owner | No automatic repository access implied | Product direction |
|
||||
| Organization Owner | Organization Owner | Organization administration and continuity |
|
||||
| Repository Admin | Admin | Repository settings, permissions, and protection rules |
|
||||
| Maintainer | Write by default | Implement, review, merge, and maintain |
|
||||
| Triage | Triage | Organize intake, de-duplicate, and prepare work |
|
||||
| Contributor / Platform Tester | Public / Read as appropriate | Contribute code or provide validation |
|
||||
|
||||
Maintain access may be granted when repository-management duties require it.
|
||||
|
||||
## Maintainer focus
|
||||
|
||||
- **Core Maintainer:** project-wide judgment, difficult technical decisions, governance support.
|
||||
- **Technical Maintainer:** implementation, architecture, validation, technical health.
|
||||
- **Project Maintainer:** review, contributor coordination, documentation, releases, organization.
|
||||
|
||||
These are responsibility labels. No label automatically changes GitHub permissions or overrides the [review rules](changes-and-review.md).
|
||||
|
||||
## Functional responsibilities
|
||||
|
||||
Maintainers may coordinate Release, Security, Infrastructure and CI, Community, or Test and Validation. These are duties, not ranks. For each release, designate one Release Maintainer and record the handoff if ownership changes.
|
||||
|
||||
## Least privilege and continuity
|
||||
|
||||
Grant access because it is necessary for current work, not because of a title. GitHub, Matrix, Plane, infrastructure, SSH, deployment systems, secrets, and external services are separate access surfaces.
|
||||
|
||||
For elevated or sensitive access, document a responsible owner and recovery route in an appropriate **private** administrative system. Do not publish tokens, SSH details, personal addresses, or credential locations in this handbook. Remove access promptly when it is no longer needed.
|
||||
|
||||
## Inactivity
|
||||
|
||||
Tell an admin when you expect to be unavailable; a communicated absence is fine.
|
||||
|
||||
If there is no meaningful maintainer or triage activity for **two months**, no prior notice, and no response to reasonable follow-up, elevated access may be reviewed and removed. This is access hygiene, not punishment. Returning members may regain access appropriate to their active responsibilities.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Testing and releases
|
||||
|
||||
Validation must match the actual change, and evidence must state what was **run**, **observed**, and **not tested**.
|
||||
|
||||
`dev` is the integration and stabilization branch. `main` is the curated release destination. Changes land in `dev`; a release promotes a verified `dev` revision to `main`.
|
||||
|
||||
## Runtime isolation
|
||||
|
||||
Run contributor-controlled tests, builds, installs, and repros in an isolated, secretless environment. Use disposable containers or microVMs where appropriate, with no credentials, sensitive host files, production data, or host/container-management sockets exposed. If safe isolation is unavailable, record the check as not run.
|
||||
|
||||
Agents may use a skill for the maintainer's preferred environment and handling; the same isolation requirements apply.
|
||||
|
||||
## Change validation
|
||||
|
||||
- Run focused tests that cover the modified behavior and failure cases.
|
||||
- Run broader regressions where risk crosses module boundaries.
|
||||
- For authentication, data loss, or similar high-risk work, include adversarial and rollback tests.
|
||||
- Reproduce the issue on the pre-fix version when safe and practical, then prove the correction.
|
||||
- For visual changes, run the application and attach the screenshots or clips required by [CONTRIBUTING.md](../../CONTRIBUTING.md).
|
||||
- Record exact commands, environment, result, skipped tests, and blockers. Never claim execution from a command you did not run.
|
||||
|
||||
GitHub Actions success means a workflow finished successfully; it does **not** mean CodeQL found no alerts. Use [review playbook](review-playbook.md#codeql-and-security-scanning) to assess findings separately. A review must tie required CI and the final diff to the **same commit SHA**.
|
||||
|
||||
## Supported-environment evidence
|
||||
|
||||
Platform Testers may validate without maintainer permissions. Useful coverage includes:
|
||||
|
||||
- Windows native and WSL.
|
||||
- macOS Apple Silicon.
|
||||
- macOS Intel while supported.
|
||||
- Linux native on the reference distribution.
|
||||
- Docker on supported hosts.
|
||||
|
||||
Record the environment and configuration for each result. Do not imply that a platform was tested when it was not.
|
||||
|
||||
## Release ownership
|
||||
|
||||
A designated **Release Maintainer** owns preparation and the publish decision once the release criteria are met. Other maintainers and testers supply the evidence needed for the change set. If the Release Maintainer becomes unavailable, another maintainer explicitly takes over.
|
||||
|
||||
## Release checklist
|
||||
|
||||
Before promoting `dev` to `main`:
|
||||
|
||||
1. Identify and freeze the release candidate SHA; check the actual content that will ship.
|
||||
2. Verify required checks and relevant supported-environment validation.
|
||||
3. Confirm high-risk and data-migration findings are resolved or addressed through an explicit approved plan.
|
||||
4. Document skipped coverage, known issues, compatibility and upgrade implications.
|
||||
5. Prepare the version, tag, artifacts, and release notes.
|
||||
6. Confirm rollback/recovery, including any manual persistence or data migration steps.
|
||||
7. Publish and record what was promoted, the verification evidence, and operational follow-ups.
|
||||
|
||||
Publishing does not require ceremonial Core or domain sign-off when the criteria are met. Exceptional or disputed releases follow the normal high-risk escalation path.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Triage
|
||||
|
||||
Triage turns reports into evidence-backed work that a maintainer can pick up without guessing.
|
||||
|
||||
## Intake flow
|
||||
|
||||
```text
|
||||
Report
|
||||
-> reproduce / clarify
|
||||
-> identify duplicates and affected versions
|
||||
-> classify impact, urgency, and risk
|
||||
-> prepare actionable work item
|
||||
-> maintainer takes ownership
|
||||
-> PR, verification, and follow-up
|
||||
```
|
||||
|
||||
## A useful work item
|
||||
|
||||
Record what is known and distinguish it from what remains unverified:
|
||||
|
||||
- Original report and reproducible steps; installation method, OS, version/commit, and relevant environment.
|
||||
- Expected versus actual behavior, including user-visible impact.
|
||||
- Evidence: sanitized logs, screenshots, failing tests, or controlled reproduction.
|
||||
- Related issues, PRs, duplicates, or a known prior regression.
|
||||
- Scope, acceptance criteria, and non-goals.
|
||||
- Priority, ownership, and relevant domain expertise.
|
||||
- Remaining unknowns, risks, and safe recovery or workaround when available.
|
||||
|
||||
Small and obvious fixes may go straight to a focused PR, consistent with [CONTRIBUTING.md](../../CONTRIBUTING.md) and [changes and review](changes-and-review.md).
|
||||
|
||||
## Practical priority language
|
||||
|
||||
Use P0-P3 as **triage shorthand**, not as a substitute for verified exploitability or the project's actual GitHub labels:
|
||||
|
||||
| Priority | Typical impact | Expected response |
|
||||
|---|---|---|
|
||||
| P0 | Active exploitation, broad irreversible loss, catastrophic outage | Immediate containment and escalation |
|
||||
| P1 | Credible severe security or data-integrity vulnerability | Urgent owner assignment and validated fix |
|
||||
| P2 | Significant correctness, security, or operational regression | Prioritize and resolve before approving affected high-risk changes |
|
||||
| P3 | Limited impact, maintainability, or low-risk polish | Fix or explicitly track with rationale |
|
||||
|
||||
Do not call a concern harmless merely because an automated check is green. Escalate privately when reproduction would disclose a vulnerability.
|
||||
|
||||
## Where decisions live
|
||||
|
||||
Matrix is for coordination; durable decisions belong in GitHub, Plane, a specification, or the relevant PR. Keep confidential security and access details in appropriate private channels. Do not leave important project decisions only in chat history.
|
||||
|
||||
See the [review playbook](review-playbook.md) for converting triage into review evidence and handling contested or uncertain findings.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Upstream SearXNG trust validation
|
||||
|
||||
SearXNG owns independent system and Python certificate stores. Updating Odysseus's Python environment does not update this sidecar. The base and both standalone GPU Compose files now select the official `docker.io/searxng/searxng:2026.10.24-ef0ec03da` image at immutable multiarch digest `sha256:7c7cbe509429e82755104b2a95f52085a98633c95d53f44e4e905fa3a59f08c8`. Its system and certifi stores remove the affected eMudhra trust. The [upstream certifi update](https://github.com/searxng/searxng/pull/6881) is included in this release.
|
||||
|
||||
Deploy the upstream image directly. The validation Dockerfile adds public fixtures and diagnostics only; no repair layer, custom runtime image or project registry publisher is required. `scripts/check_ca_trust.py` owns the known-certificate inventory for both the application and SearXNG checks.
|
||||
|
||||
## Validate a pin update
|
||||
|
||||
Run from the repository root on a disposable Docker host. The helper uses a fresh configuration volume, omits published ports and does not load the operator's `.env`. It retains the base Compose settings wrapper, healthcheck and capabilities. Outbound network access and working search engines are required for the live checks.
|
||||
|
||||
```sh
|
||||
image=$(docker compose --env-file /dev/null -f docker-compose.yml config --format json |
|
||||
python3 -c 'import json, sys; print(json.load(sys.stdin)["services"]["searxng"]["image"])')
|
||||
|
||||
# Offline build-step checks, including actual entrypoint and loopback health.
|
||||
# Pulling the selected base still requires registry access.
|
||||
docker build --network=none --target validation \
|
||||
--build-arg "SEARXNG_IMAGE=$image" -f docker/searxng/Dockerfile .
|
||||
|
||||
# Exercise the exact unmodified deployment image after an anonymous pull.
|
||||
docker pull "$image"
|
||||
bash .github/scripts/validate-searxng-image.sh "$image"
|
||||
```
|
||||
|
||||
The offline checks require all fourteen incident chains to fail certificate verification through the system PEM bundle, hashed CA directory and certifi. The affected positive-control roots must accept those same chains. Each fixture's DER fingerprint is verified first, and a fixed verification timestamp prevents expiry from hiding a broken mitigation. Checks run again after the real upstream root entrypoint regenerates trust.
|
||||
|
||||
The live checks use SearXNG's actual curl client factory. Ordinary verified HTTPS must succeed, all fourteen incident hosts must fail with curl certificate error 60, and a JSON search must return results. DNS failures, timeouts and generic handshake failures are inconclusive and fail validation. The checks inspect the already-running service without changing its trust stores.
|
||||
|
||||
The `ci / SearXNG trust` workflow runs these offline and Compose/live checks on native amd64 and arm64 runners. It selects the same immutable image as base Compose, pulls without registry credentials, and has read-only repository permissions. It neither publishes a replacement image nor requires package-write credentials. Update all three deployment pins together; the alignment regression guards the standalone GPU files.
|
||||
|
||||
## Rollout and scope
|
||||
|
||||
Changing a Compose pin does not replace running containers. After updating the checkout, run `docker compose pull searxng` and `docker compose up -d --no-deps searxng`, then inspect health, retained settings and actual Odysseus search integration. Use the appropriate standalone GPU Compose file when that is the deployment being managed.
|
||||
|
||||
Operator-mounted trust, custom engines, persisted packages and independently managed clients need separate effective-client checks. An amd64 result does not establish arm64 behavior. The fixture-based check detects known certificate fingerprints; it does not model every native revocation mechanism or arbitrary reissued certificates sharing a compromised key. See [outbound TLS trust](tls-trust.md) for the application, bootstrap, Chromium and other runtime boundaries.
|
||||
|
||||
## Public fixture provenance
|
||||
|
||||
The public CA inventory comes from the incident's [roots](https://emudhra.we-have-a-problem.com/roots.json) and [intermediates](https://emudhra.we-have-a-problem.com/impacted-intermediates.json). The additional cross-signed issuer and fourteen chain fixtures come from [chains.zip](https://emudhra.we-have-a-problem.com/chains.zip), SHA-256 `7b949956955fc501a30f4d98d2f513d34c0bbbe92e29a968194c96e097ce2345`. Fixtures contain public certificates only. See [the fixture notes](../tests/fixtures/ca-trust/README.md).
|
||||
@@ -0,0 +1,75 @@
|
||||
# Outbound HTTPS trust
|
||||
|
||||
Odysseus uses both Python package CA bundles and system trust. HTTPX uses certifi by default; the guarded web/PDF fetcher and webhook delivery explicitly use Python's system SSL context. A configured `LLM_CA_BUNDLE` adds certificates to system trust for model calls. Upgrading certifi alone cannot repair every outbound HTTPS path.
|
||||
|
||||
For the October 2026 eMudhra incident, use certifi 2026.10.23 or newer, pip 26.2.2 or newer, and uv 0.13.5 or newer wherever uv is used. Pip has its own vendored certifi and also loads system roots. Update the operating system's certificate package separately. See the [Python security announcement](https://discuss.python.org/t/109576) and [incident details](https://emudhra.we-have-a-problem.com/).
|
||||
|
||||
Before other pip installs, bootstrap the selected environment with the integrity-pinned wheels:
|
||||
|
||||
```sh
|
||||
python -m pip install --require-hashes --only-binary=:all: --no-deps -r requirements-bootstrap.txt
|
||||
python -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
The pinned bootstrap protects package integrity even when the old installer's certificate bundle is affected. It is not an operating-system trust-store update. Native Windows/macOS trust and command-line OpenSSL PEM stores may differ; follow the platform vendor's remediation for every store in use. Restart Odysseus and its subprocesses after updating trust.
|
||||
|
||||
On Linux/OpenSSL deployments, inspect both the effective CA file and hashed CA directory, plus the two Python bundles:
|
||||
|
||||
```sh
|
||||
python scripts/check_ca_trust.py --system --python --overrides --verbose
|
||||
```
|
||||
|
||||
Explicit PEM bundles can also be passed as positional arguments. The check rejects the four published root fingerprints, all sixteen published intermediate certificates (including their cross-signs), the cross-signed G3 issuer in the published test chains, and malformed/empty bundles. Checking intermediates matters because adding one as a custom trust anchor can restore an affected chain even after its roots have been removed.
|
||||
|
||||
`--overrides` checks every nonempty `LLM_CA_BUNDLE`, `SSL_CERT_FILE`, `REQUESTS_CA_BUNDLE`, `CURL_CA_BUNDLE`, `PIP_CERT`, `NODE_EXTRA_CA_CERTS` and `GRPC_DEFAULT_SSL_ROOTS_FILE_PATH` setting in the checker's process environment, including configured fallback settings. Requests/pip hashed-directory overrides are inspected too; `--system` covers `SSL_CERT_DIR`. Run with the application's environment and filesystem access. The script does not load `.env` or application configuration files; pass any CA paths configured only there explicitly, for example `python scripts/check_ca_trust.py --system --python /path/to/private-ca.pem`. Missing or invalid configured files fail the check. Selecting only `--overrides` with no configured paths also fails instead of reporting that stores were validated.
|
||||
|
||||
`--verbose` reports the Python executable/prefix, user home, effective UID/GID where available, and resolved CA paths, including bundles selected from user-installed packages. Compare these with the running application's identity and interpreter. It does not dump environment variables or credentials.
|
||||
|
||||
This is an offline inventory check of known certificate fingerprints. It does not modify stores, reject requests at runtime, model native OS revocation, or detect arbitrary reissued certificates sharing the compromised keys. Chromium's policy separately matches public keys. Check mounted or replaced CA files again after deployment, remove affected trust through the owning platform/client configuration, and restart clients that cache SSL contexts. A passing build cannot validate custom files introduced later.
|
||||
|
||||
Both Docker build stages use Python 3.14.9, refresh system CA certificates and bootstrap pip/certifi before dependency installation. The build fails if known affected CA certificates remain. Node uses the corrected system store through `--use-openssl-ca`. Python gRPC uses that same PEM file through `GRPC_DEFAULT_SSL_ROOTS_FILE_PATH`; updating certifi alone does not replace gRPC's independent wheel bundle. After dependency installation, the image checks gRPC's selected file as well. An explicit gRPC override must be readable and free of known affected CA certificates. [grpcio 1.84.1](https://github.com/grpc/grpc/releases/tag/v1.84.1) includes the upstream root-bundle correction and is the application minimum. Retain the checked override as a consistent image trust selection; older persisted Python environments and explicit client roots still need independent checks.
|
||||
|
||||
The image also bundles Docker CLI [29.9.2](https://github.com/moby/moby/releases/tag/docker-v29.9.2), built with Go 1.26.10's distrust of the compromised intermediate keys. Cookbook uses this client for optional Docker operations. Default Compose does not mount the host Docker socket; local daemon access requires the explicit [host-Docker overlay](../docker/host-docker.yml), whose usual Unix-socket connection does not use TLS. The client update is maintenance of a shipped tool, not evidence that these local calls were exposed. It does not update the host daemon or other containers' clients and trust stores; assess those separately.
|
||||
|
||||
Chromium uses a separate trust store. The Docker image installs a managed `CADistrustedCertificates` policy for the eight compromised intermediate public keys, covering their cross-signs without depending on background revocation updates. It adds no trusted certificate and does not disable certificate verification. The policy and public-certificate provenance are documented in [the browser policy note](../docker/chromium-ca-policy.md). Native browser installations and independently managed profiles require their own platform policy or vendor update; this image policy does not configure host browsers.
|
||||
|
||||
To replace only Odysseus in an already running Compose stack, build from the corrected checkout with a distinct local image tag. Use the same Compose files and project name as the existing deployment for every command below:
|
||||
|
||||
```sh
|
||||
export ODYSSEUS_IMAGE="odysseus-local:ca-$(git rev-parse --short=12 HEAD)"
|
||||
docker compose build --pull --no-cache odysseus
|
||||
docker compose up -d --no-deps --pull never --no-build odysseus
|
||||
docker image inspect --format '{{.Id}}' "$ODYSSEUS_IMAGE"
|
||||
docker inspect --format '{{.Image}}' "$(docker compose ps -q odysseus)"
|
||||
```
|
||||
|
||||
The two image IDs must match. Keep the selected `ODYSSEUS_IMAGE` in the deployment configuration for subsequent recreations. Compose can prefer the registry image when both `image` and `build` are present; the explicit pull/build flags keep this replacement on the local build. `--no-deps` leaves the existing sidecars running and is intended for an existing stack. For registry deployments, select a verified corrected immutable tag or digest. A merge to `dev` publishes `:dev`; it does not update `:latest`, which is published from `main`.
|
||||
|
||||
Check the standard image as its configured app account, using the image's Python interpreter and the same user-bin PATH prefix as the entrypoint:
|
||||
|
||||
```sh
|
||||
docker compose exec -T --user 0 odysseus sh -ec '
|
||||
gosu_bin=$(command -v gosu)
|
||||
app_user=$(getent passwd "${PUID:-1000}" | cut -d: -f1)
|
||||
test -n "$app_user"
|
||||
exec "$gosu_bin" "$app_user" env PATH="/app/.local/bin:$PATH" \
|
||||
/usr/local/bin/python /app/scripts/check_ca_trust.py \
|
||||
--system --python --grpc --overrides --verbose
|
||||
'
|
||||
```
|
||||
|
||||
`gosu` selects the account's HOME and drops privileges before Python runs, so the check includes its persisted user packages. The entrypoint itself is not rerun. Plain `docker compose exec ... python` uses the image's default root user and can miss `/app/.local` packages. A custom service user, entrypoint, virtual environment or launch command requires matching that deployment's actual user, HOME and Python interpreter instead of copying the standard command unchanged. Docker exec inherits container-creation environment, not variables exported later by the app or entrypoint: reproduce any additional Python/TLS settings with exec's `--env` options, and pass CA paths configured only in application files explicitly. Confirm the verbose identity and selected paths before accepting the result.
|
||||
|
||||
For containers started non-root or without the SETUID/SETGID capabilities needed by `gosu`, use `docker compose exec --user UID:GID --env HOME=/actual/app/home` with the deployment's actual numeric IDs, home, PATH and interpreter instead. Do not add capabilities merely to run this check.
|
||||
|
||||
SearXNG is a separate HTTPS client and image; updating the Odysseus image does not patch it. Inspect its effective CA path and update or rebuild that image independently. Also inspect persisted `/app/.local` packages, remote Cookbook environments, and externally configured MCP runtimes. Image replacement does not necessarily replace those environments.
|
||||
|
||||
For behavioral validation, all fourteen [published test chains](https://emudhra.we-have-a-problem.com/chains.zip), including the AAA cross-signs and two chains without Certificate Transparency entries, must fail certificate verification through the effective stores. Confirm that an ordinary known-good HTTPS request still succeeds. In Chromium, confirm the managed policy is loaded at `chrome://policy` and test the incident endpoints through the actual browser path with certificate verification enabled. The PEM checker cannot inspect Chromium's policy or its active verifier. Package versions and a successful image build alone do not prove that a running deployment selects the corrected store.
|
||||
|
||||
## Follow-up releases
|
||||
|
||||
The maintained bootstrap selects certifi 2026.10.23 with its verified wheel hash; pip remains 26.2.2. The certifi update removes the C1/C3 roots in addition to the earlier incident changes. CI uses uv 0.13.5, which adds verifier-level rejection of the compromised intermediate keys and updated managed CPython builds. Existing virtual environments do not update automatically. See the [certifi change](https://github.com/certifi/python-certifi/commit/b60466c9f2882d9cf088943c650b0faac06c080c), [uv release](https://github.com/astral-sh/uv/releases/tag/0.13.5), and [Python security releases](https://blog.python.org/2026/10/python-3151-3149-31317/). The pinned bootstrap still replaces the selected versions exactly; preserving newer installed versions and private-mirror support remain separate maintenance.
|
||||
|
||||
SearXNG remains an independent trust owner. Use the [upstream-image validation and rollout instructions](searxng-trust-image.md); updating these application packages does not repair an existing sidecar. Host daemons, native browser policy, optional compiled clients and independently managed integrations require their own effective-client checks.
|
||||
|
||||
CPython's [intermediate-key verifier block](https://github.com/python/cpython/pull/160042) and its [3.14 backport](https://github.com/python/cpython/pull/160569) merged on October 24. They are distinct from Python 3.14.9's bundled-pip update. No released 3.14 interpreter containing that verifier change was identified when this image pin was selected; retain the corrected effective trust stores and track the subsequent security release. hf-xet's [trust fix](https://github.com/huggingface/xet-core/pull/1038) is also merged but not included in the latest published 1.7.0 release at that check. Agent-browser 0.39.2 and primp 2.0.1 are not established incident fixes for their independent native trust paths. A version bump alone does not establish that the active client uses corrected trust.
|
||||
Reference in New Issue
Block a user