12 Commits
Author SHA1 Message Date
Kevin CodexandClaude Opus 4.7 14a1cdd656 chore: bump v0.3.9, fix all clippy warnings, enforce strict CI lint (#12)
* chore: bump v0.3.9, fix all clippy warnings, enforce strict CI lint

- Bump workspace version 0.3.8 → 0.3.9
- Fix 22 clippy warnings across 17 files:
  - Replace .last() with .next_back() on DoubleEndedIterators (8 instances)
  - Remove useless .into() conversions on anyhow::Error (3)
  - Remove needless borrows in gl init (3)
  - Replace map_or with is_some_and/is_none_or (3)
  - Collapse consecutive str::replace into char array pattern (2)
  - Change &PathBuf to &Path in function signatures (2)
  - Remove dead code: unused init_bare_repo function
  - Collapse if-let into outer match arm
  - Replace vec![...] with array literal
  - Introduce RecordAnchorInput struct (10 params → 1 struct)
  - Fix always-true boolean condition in gossip task guard
- Promote clippy from advisory to strict (-D warnings) in CI

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* style: cargo fmt

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
v0.3.9
2026-05-27 10:28:14 +08:00
rapybus be099386e5 Update bootstrap-peers.json (#5) 2026-05-27 09:38:12 +08:00
b09714af0b fix(doctor): detect git-remote-gitlawb.exe on Windows (#10)
which_in_path() now also checks for `{name}.exe` on Windows targets,
so `gl doctor` correctly finds git-remote-gitlawb on that platform.

Co-authored-by: kelvinzer0 <[email protected]>
Co-authored-by: OpenClaude (mimo-v2.5-pro) <[email protected]>
2026-05-27 09:37:58 +08:00
Rimantas (Rimas) MoceviciusandRimas Mocevicius d09c23da86 feat: macOS menu bar app for managing gitlawb-node Docker Compose stack (#8)
- Menu bar icon with colored status dot (green/yellow/red)
- Start/Stop node via Docker Compose
- Settings UI: ports, public URL, postgres password, auto-sync, operator config
- View Logs window with live docker compose logs
- Auto-start on launch and login (SMAppService)
- Docker detection with install prompt
- Repo root detection via compile-time path for local builds
- Port variables wired through docker-compose.yml for custom port support
- GITLAWB_AUTO_SYNC passthrough for peer replication toggle
- Build script: scripts/build-macos-app.sh (codesign + DMG)

Co-authored-by: Rimas Mocevicius <[email protected]>
2026-05-27 09:37:36 +08:00
Esky33 f3df4a4dd4 Resolve bare DID aliases for trust and cert lookups (#9)
* Resolve bare DID aliases for trust and cert lookups

Public profile and CLI surfaces accept bare z6Mk keys, but trust and certificate data are stored against full did:key identities. Normalize agent profile lookups and make cert commands resolve owner-less repos against the caller DID so valid pushes are not hidden behind node-owned paths.

Constraint: Public URLs and CLI examples commonly use short z6Mk identifiers

Constraint: Ref certificates are issued after push and stored under the owner repo id

Rejected: Register duplicate bare-key identities | would split trust and certificate history across aliases

Rejected: Require full certificate UUIDs in show output | list already displays short IDs as the human-facing handle

Confidence: high

Scope-risk: narrow

Directive: Keep bare key inputs as aliases for did:key, not separate identities

Tested: cargo check -p gl

Tested: cargo run -q -p gl -- cert list agentbot-opensource

Tested: cargo run -q -p gl -- cert show agentbot-opensource 3686b1fe

Tested: cargo check -p gitlawb-node

Tested: cargo test -p gitlawb-node normalize_agent_did

* Preserve agent rank on short profile URLs

The public profile route can use compact handles like z6MkpUq1, while trust history is stored under the full did:key identity. Resolve exact aliases first, then fall back to matching registered agent key prefixes so older high-level identities are not displayed as fresh newcomers.

Constraint: Public GitLawb profile URLs expose short z6Mk handles.

Constraint: Trust and push history remain keyed by canonical did:key identities.

Rejected: Mint duplicate short-handle agent rows | would split rank and push history across aliases.

Confidence: high

Scope-risk: narrow

Directive: Keep short profile handles as aliases for canonical did:key identities, never as separate trust principals.

Tested: cargo fmt --check -p gitlawb-node

Tested: cargo test -p gitlawb-node agent

Tested: cargo check -p gitlawb-node

Tested: cargo check -p gl
2026-05-27 09:36:37 +08:00
Kevin CodexandOpenClaude 034cb3c80c feat: replica registration protocol (Phase 2 v1) (#4)
Phase 2 of the network-resilience plan: any node can register itself as a
replica of someone else's repo, and the origin exposes the replica list
publicly as a "your repo is mirrored by N nodes" trust signal.

What ships
- New repo_replicas table keyed by (repo_id, replica_did) with replica URL
  and registration timestamp. UNIQUE on (repo_id, replica_did); duplicate
  registrations update the URL.
- API on origin:
    PUT  /api/v1/repos/:owner/:repo/replicas   (auth) register
    DELETE /api/v1/repos/:owner/:repo/replicas (auth) unregister
    GET  /api/v1/repos/:owner/:repo/replicas   (public) list
  Origin rejects self-registration and validates the replica URL (http(s),
  no whitespace/control chars, length-bounded).
- CLI:
    gl repo replica-register <owner>/<repo> --url <my-public-url>
    gl repo replica-unregister <owner>/<repo>
    gl repo replicas <owner>/<repo>
- gl repo info now shows "Replicas: N" when the origin supports it.
- Tests: 5 new unit tests for the URL validator. Full node suite at 51 pass,
  full gl suite at 188 pass.

Deferred to Phase 2.5
- Replica auto-pulls the repo on registration (today: operator runs
  git clone gitlawb://... manually after registering).
- Periodic freshness sync worker driven by the replica list.
- Gossipsub subscription to push ref-update events to replicas live.

Co-authored-by: OpenClaude <[email protected]>
2026-05-27 09:36:12 +08:00
d2a440e521 Feat/backport perf fixes (#11)
* feat: replica registration protocol (Phase 2 v1)

Phase 2 of the network-resilience plan: any node can register itself as a
replica of someone else's repo, and the origin exposes the replica list
publicly as a "your repo is mirrored by N nodes" trust signal.

What ships
- New repo_replicas table keyed by (repo_id, replica_did) with replica URL
  and registration timestamp. UNIQUE on (repo_id, replica_did); duplicate
  registrations update the URL.
- API on origin:
    PUT  /api/v1/repos/:owner/:repo/replicas   (auth) register
    DELETE /api/v1/repos/:owner/:repo/replicas (auth) unregister
    GET  /api/v1/repos/:owner/:repo/replicas   (public) list
  Origin rejects self-registration and validates the replica URL (http(s),
  no whitespace/control chars, length-bounded).
- CLI:
    gl repo replica-register <owner>/<repo> --url <my-public-url>
    gl repo replica-unregister <owner>/<repo>
    gl repo replicas <owner>/<repo>
- gl repo info now shows "Replicas: N" when the origin supports it.
- Tests: 5 new unit tests for the URL validator. Full node suite at 51 pass,
  full gl suite at 188 pass.

Deferred to Phase 2.5
- Replica auto-pulls the repo on registration (today: operator runs
  git clone gitlawb://... manually after registering).
- Periodic freshness sync worker driven by the replica list.
- Gossipsub subscription to push ref-update events to replicas live.

Co-Authored-By: OpenClaude <[email protected]>

* perf: backport query optimizations + add Fly test deployment

- Add expression indexes (owner_short+name, updated_at DESC) for fast repo listing
- Add list_all_repos_with_stars() batch query eliminating N+1 star count calls
- Add list_all_repos_paged() with DISTINCT ON dedup + pagination + X-Total-Count header
- Add prune_self_peers() to remove stale self-referencing peer rows at startup
- Add self-loop prevention in HTTP peer notifications during git-receive-pack
- Add SwarmStatus observability to p2p_info endpoint (connected/mesh/all peers)
- Add fly.toml for gitlawb-node-test deployment in iad region

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

---------

Co-authored-by: OpenClaude <[email protected]>
Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-27 09:35:46 +08:00
Kevin CodexandOpenClaude f312955c35 feat: replica registration protocol (Phase 2 v1) (#3)
Phase 2 of the network-resilience plan: any node can register itself as a
replica of someone else's repo, and the origin exposes the replica list
publicly as a "your repo is mirrored by N nodes" trust signal.

What ships
- New repo_replicas table keyed by (repo_id, replica_did) with replica URL
  and registration timestamp. UNIQUE on (repo_id, replica_did); duplicate
  registrations update the URL.
- API on origin:
    PUT  /api/v1/repos/:owner/:repo/replicas   (auth) register
    DELETE /api/v1/repos/:owner/:repo/replicas (auth) unregister
    GET  /api/v1/repos/:owner/:repo/replicas   (public) list
  Origin rejects self-registration and validates the replica URL (http(s),
  no whitespace/control chars, length-bounded).
- CLI:
    gl repo replica-register <owner>/<repo> --url <my-public-url>
    gl repo replica-unregister <owner>/<repo>
    gl repo replicas <owner>/<repo>
- gl repo info now shows "Replicas: N" when the origin supports it.
- Tests: 5 new unit tests for the URL validator. Full node suite at 51 pass,
  full gl suite at 188 pass.

Deferred to Phase 2.5
- Replica auto-pulls the repo on registration (today: operator runs
  git clone gitlawb://... manually after registering).
- Periodic freshness sync worker driven by the replica list.
- Gossipsub subscription to push ref-update events to replicas live.

Co-authored-by: OpenClaude <[email protected]>
2026-05-13 20:00:40 +08:00
Kevin CodexandOpenClaude ec4ef81770 feat: embed bootstrap peers seed list for automatic network discovery (#1)
* feat: embed bootstrap peers seed list for automatic network discovery

A fresh \`docker compose up\` now joins the Gitlawb network with zero
manual peer configuration. The node parses an embedded \`bootstrap-peers.json\`
on startup and merges the entries into both the HTTP gossip task and the
libp2p Kademlia bootstrap.

- Add \`bootstrap-peers.json\` at repo root (versioned schema, PR-friendly)
- New \`bootstrap\` module in the node crate (parse + merge_seeds)
- Wire into \`main\` after \`Config::parse\`
- Operators can opt out via \`GITLAWB_BOOTSTRAP_DISABLE_SEEDS\` for
  isolated dev networks

Also in this commit:
- \`cargo fmt --all\` over the entire workspace (no logic changes)
- Downgrade CI clippy step to advisory (\`continue-on-error: true\`) until
  the existing lint backlog is cleared. fmt + tests stay strict.

Co-Authored-By: OpenClaude <[email protected]>

* test: cover bootstrap merge logic with unit tests

Refactor bootstrap.rs into pure functions (parse_seed_list, merge_into_vecs)
so the parse + merge logic can be tested without constructing a Config or
mutating process-global env vars.

Adds 11 tests covering:

- valid v1 list parses
- unknown version is rejected
- malformed JSON is rejected
- empty / missing peers array
- merge appends new http + p2p entries
- merge dedupes against existing entries
- invalid p2p_multiaddr is skipped (http still added)
- empty strings are skipped
- null optional fields are tolerated
- the canonical bootstrap-peers.json shipped in the repo always parses
  (regression guard against future schema changes)

Co-Authored-By: OpenClaude <[email protected]>

* fix(security): reject path traversal in repo_store local_path

Closes CodeQL alert #4 (Uncontrolled data used in path expression).

Both `owner_did` and `repo_name` come from URL parameters and were used
unsanitized to build a filesystem path, so a request like
`/did:key:foo/../../../etc/passwd.git/info/refs` could escape the repos
directory.

Fix:

- New `validate_owner_did` and `validate_repo_name` enforce a strict
  allowlist before path construction (alphanumeric + `: . _ -` for DIDs;
  alphanumeric + `. _ -` for repo names; rejects empty, `..`, leading
  `.` or `-`, slashes, backslashes, null bytes, overlong inputs).
- `RepoStore::local_path` now returns `Result<…>` and the 5 callers
  propagate the error.
- Defence in depth: even after the allowlist passes, the joined path is
  checked to still be rooted at `repos_dir`.
- 17 unit tests cover normal DIDs/repo names plus every malicious shape
  (`..`, `/`, `\`, leading dot/dash, null byte, overlong, did:web with
  dots).

Co-Authored-By: OpenClaude <[email protected]>

* fix(security): add Path::components barrier for CodeQL rust/path-injection

CodeQL's rust/path-injection query did not recognise the existing
allowlist validator as a sanitiser, so it kept flagging local_path even
though every malicious input was already rejected.

Adds an explicit Path::components() walk after path construction that
rejects any ParentDir or CurDir segment. This is the barrier pattern
CodeQL recognises — and is also genuine defence-in-depth in case a
future change ever weakens the allowlist.

Allowlist + starts_with + components walk = three independent layers
between attacker-controlled HTTP input and filesystem access. All 17
existing tests still pass.

Co-Authored-By: OpenClaude <[email protected]>

---------

Co-authored-by: OpenClaude <[email protected]>
2026-05-13 19:11:54 +08:00
Kevin CodexandOpenClaude 068fc76899 fix: nuke dummy binaries + fingerprints before second cargo build
Touch alone wasn't enough — cargo can still reuse cached fingerprint
state from the dependency-cache layer. Explicitly remove the dummy
binaries and their fingerprint dirs so the second build reproduces
real artifacts unconditionally.

Also drop the obsolete `version: '3.9'` from docker-compose.yml.

Co-Authored-By: OpenClaude <[email protected]>
2026-04-29 17:08:43 +08:00
Kevin CodexandOpenClaude 49dadf5172 fix: force cargo rebuild in docker layer
Touch real source files after COPY so cargo's fingerprint check
detects the change and rebuilds from real source. Without this,
cargo can keep the dummy `fn main() {}` binaries from the
dependency-cache layer, causing the runtime container to exit
immediately with code 0.

Co-Authored-By: OpenClaude <[email protected]>
2026-04-29 17:04:09 +08:00
Kevin CodexandOpenClaude 6b9c5278d4 chore: initial public release
Open-source release of the gitlawb node, CLI, and git remote helper.

- gitlawb-node: Axum HTTP server with git smart-HTTP and DID auth
- gl: command-line client (identity, repos, PRs, MCP server)
- git-remote-gitlawb: git remote helper for gitlawb:// URLs
- gitlawb-core: shared crypto primitives (DID, CID, HTTP sigs, UCAN)

Dual licensed under MIT or Apache-2.0.

Co-Authored-By: OpenClaude <[email protected]>
2026-04-29 16:34:27 +08:00