[pull] main from Open-Legal-Products:main
From the PR description
See Commits and Changes for more details.
Created by pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )
Our analysis
Merge fork updates — read the full analysis →
Think the analysis missed something the PR description covers?
Commits in this PR (12)
| SHA | Subject | Author | Date | |
|---|---|---|---|---|
562a8139 | feat: content hashes on document versions + signed project export manifest | Andy | 2026-07-31 | ↗ GitHub |
commit bodyStores a SHA-256 of every document version's bytes at write time and adds a per-project export manifest listing them alongside the accept/reject trail, so an exported file set can be checked against what the workspace held. The manifest carries a SHA-256 digest over a canonical form of its body, Ed25519-signed when MANIFEST_SIGNING_KEY is set. Signing is optional so a self-hosted deployment without key custody can still export; a malformed key throws rather than silently downgrading to unsigned. The signature covers a versioned context string and a NUL byte before the digest bytes, so it cannot be replayed as a signature over another object, and it verifies with any Ed25519 library. The public key is served at GET /manifest-signing-key. Rebase of #181 onto current main, plus the signing requested on that PR. | ||||
18a00513 | Address review on the export manifest | Andy | 2026-07-31 | ↗ GitHub |
commit body- canonicalize rejects non-plain objects. A Date serialised as {}, a
Buffer enumerated its indices, a Map became {}. None can reach a
manifest body today, but a silently wrong serialisation is the same
failure class as the non-finite number already rejected, and every
digest rests on this function.
- Validate MANIFEST_SIGNING_KEY at boot. A malformed key previously
surfaced when a user's first export failed; it now stops startup with
the same message, and a working key logs its key id.
- Bulk copy takes size_bytes from the bytes being hashed rather than
inheriting it from the active version, so size and content_sha256
always describe the same content. A verifier that stats a file before
hashing it should not see a size that disagrees with the hash.
- README notes that soft-deleted versions stay in the manifest. Dropping
them would weaken the attestation, but it makes their filenames and
timestamps visible to anyone with project access, which is worth
stating rather than leaving to be discovered.
| ||||
9db99e1c | feat: add workflow slash triggers | Sol Irvine | 2026-08-02 | ↗ GitHub |
d54684d6 | feat: show empty slash command state | Sol Irvine | 2026-08-03 | ↗ GitHub |
75a10f08 | fix: pass through slash without commands | Sol Irvine | 2026-08-03 | ↗ GitHub |
f75914ca | ci(security): SECURITY.md, CodeQL, gitleaks, OpenSSF Scorecard | Amalanand Muthukumaran | 2026-07-25 | ↗ GitHub |
commit bodyPublic-repo security posture on top of PR #227's audit/eslint/dependabot gates: - SECURITY.md: private vulnerability reporting via the Security tab, 7-day acknowledgment (solo maintainer), self-hosted + LLM prompt-injection scope notes. main-only support (no release tags yet). - codeql.yml: javascript-typescript analysis with build-mode: none (interpreted TS, no build needed) on PRs, main, and a weekly cron. - gitleaks.yml: full-history secret scan using a sha256-verified pinned release binary instead of gitleaks-action (which needs a paid license for org repos). .gitleaks.toml allowlists hand-verified fake secrets (test fixtures, docs placeholders, the public supabase-demo anon key); a local run over all 551 commits is clean with this config. - scorecard.yml: OpenSSF Scorecard on main + weekly cron with publish_results: true. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> | ||||
a119e3e6 | fix(security-posture): pin actions to SHAs, allowlist exact secrets, correct policy scope | Amal | 2026-08-02 | ↗ GitHub |
commit bodyAddresses all four points from review on PR #246.
WHY THIS MATTERS
A security-posture PR has to hold itself to the standard it introduces.
Each of the four fixes below closes a gap where the original version
either overstated its guarantees (policy text) or quietly weakened them
(scanner allowlists, mutable action refs).
1. SECURITY.MD SCOPE - THE HOSTED SERVICE EXISTS
The policy claimed "there is no hosted service", but the official Mike
website offers a cloud version at app.mikeoss.com. A researcher reading
the old text would conclude the hosted service was out of scope and
either not report or disclose publicly. The policy now explicitly takes
hosted-service reports through the same private channel (with the usual
safe-harbor expectations: own accounts only, non-destructive testing)
and narrows the exclusion to what it was always meant to cover:
independent third-party self-hosted deployments.
2. SUPPORTED VERSIONS - TAGS EXIST AND ARE UNSUPPORTED
The repository has tags v0.1.0 through v0.4.0, so "there are no tagged
releases" was simply wrong, and wrong in the dangerous direction: a user
pinned to v0.4.0 might assume they were covered. The policy now lists
the tags explicitly as unsupported historical snapshots - only the tip
of main receives security fixes.
3. WORKFLOW ACTION PINNING - TAGS ARE MUTABLE, SHAS ARE NOT
`uses: some/action@v4` re-resolves on every run: whoever controls that
tag controls code that executes inside this repo's CI, which is exactly
how the 2025 tj-actions/changed-files compromise spread. The risk is
sharpest in the Scorecard job, which holds id-token: write (OIDC
signing) and security-events: write. Every `uses:` now references a
full commit SHA - the only immutable ref format GitHub offers - with
the release version kept in a trailing comment, which is the convention
Dependabot parses to keep proposing pinned updates:
actions/checkout@11d5960a... # v4.4.0
github/codeql-action/*@a2983b8b... # v3.37.4
ossf/scorecard-action@4eaacf05... # v2.4.3
4. GITLEAKS - ALLOWLIST EXACT SECRETS, NEVER PATHS
The old config allowlisted entire files ("this file contains a fake
secret, ignore it"). gitleaks applies a global allowlist's `paths` as a
whole-file skip, so a REAL credential later committed to any of those
files would sail through the scan - the allowlist grew a permanent
blind spot with every entry. Reproduced before fixing: planting a
high-entropy secret in an allowlisted fixture file and scanning full
history reported zero leaks under the old config.
The new config allowlists exact secret VALUES instead - one anchored
regex per hand-verified fake (the safeError test fixtures, the add-in
e2e mock token, and Supabase's published local-dev demo JWTs, which are
public by construction). A real secret can never equal a known fake, so
the blind spot is gone; the same planted-secret experiment now fails
the scan, and the full history of both this branch and current main
still passes clean. This also surfaced two findings the old path list
missed entirely (the demo JWTs in .env.example / docker-compose.yml
history) - they are now consciously allowlisted by value rather than
accidentally green.
VERIFICATION
- All three workflows parse as valid YAML.
- gitleaks 8.30.1 (checksum-verified binary): full-history scan clean
on this branch and on current origin/main with the new config.
- Planted-secret experiment: old config 0 leaks (blind), new config 1
leak (caught) on an identical history.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| ||||
25833cb7 | Merge pull request #279 from b1rdmania/feat/tamper-evident-export | Will Chen | 2026-08-03 | ↗ GitHub |
feat: content hashes on document versions + signed project export manifest | ||||
942a9ff6 | refactor: derive workflow slash commands from names | willchen96 | 2026-08-03 | ↗ GitHub |
8a92e1c2 | style: refine workflow slash menu | willchen96 | 2026-08-03 | ↗ GitHub |
afe163a3 | Merge pull request #280 from zenzen-sol/codex/workflow-slash-triggers | Will Chen | 2026-08-03 | ↗ GitHub |
feat: add workflow slash triggers | ||||
3775d534 | Merge pull request #246 from amal66/olp-pr/security-posture | Will Chen | 2026-08-03 | ↗ GitHub |
[Security 19] security posture: SECURITY.md, CodeQL, secret scan, Scorecard | ||||
Capture this PR into my fork
Download a Markdown prompt that tells Claude how to port every
commit in this PR into your working tree. Run it via
claude -p < capture-pull-17.md from
inside the repo you want the changes in.