Compare commits

...
Author SHA1 Message Date
beardthelion c7149cb695 chore: refresh PR head 2026-11-05 10:42:00 -06:00
beardthelion 49eb7d5a89 docs: drop the stale private-read priority entry 2026-09-10 21:29:16 -05:00
beardthelion 5cf3e8c7e5 fix(node): reconcile public-read messaging with per-repo enforcement
GITLAWB_PUBLIC_READ is read nowhere except a startup warning, while
read enforcement actually happens per repository through is_public and
path-scoped visibility rules. The flag's help text, the startup
warning, .env.example, and the readiness audit all still claimed
private-read enforcement was unwired.

The help and warning now state the flag is reserved and inert, and
point at the real per-repo control. A config test asserts the rendered
help neither claims enforcement is missing nor omits that the flag
does nothing.

Closes #338.
2026-09-10 19:17:24 -05:00
Kevin Codex bfc44f926d Merge pull request #381 from Gitlawb/fix/gl-whoami-capped-body-read
fix(gl): read whoami error bodies through CappedBody.text
2026-08-26 13:26:50 +08:00
beardthelion 65f5989a1d test(node): pin owner-push off in receive-pack lock tests
These lock-path proofs use non-owner proof DIDs. With enforce_owner_push
defaulting on, they fail before receive-pack runs.
2026-08-25 10:27:48 -05:00
beardthelion 4725146db2 fix(gl): read whoami error bodies through CappedBody.text
#173 changed read_body_capped to return CappedBody; peer.rs and sync.rs
were updated but whoami.rs was not, leaving main red after the #223 merge.
2026-08-25 10:04:20 -05:00
6 changed files with 41 additions and 7 deletions

No files matched your search

+2 -2
View File
@@ -108,8 +108,8 @@ GITLAWB_ENFORCE_OWNER_PUSH=true
GITLAWB_P2P_BOOTSTRAP=
# ── Access control ────────────────────────────────────────────────────────
# Reserved for private-read mode. Public/private repo read enforcement is not
# wired in the current live release; do not rely on this for private repositories.
# Reserved and currently inert. Repo reads are gated per repository by
# is_public and path-scoped visibility rules; this flag changes nothing.
GITLAWB_PUBLIC_READ=true
# Maximum git smart-HTTP pack request size, in bytes.
+9
View File
@@ -6260,6 +6260,9 @@ mod tests {
// Long enough that the git-service timeout is never what ends this push; the
// disconnect is.
cfg.git_service_timeout_secs = 600;
// Lock-path test, not owner-push authorization: pin off so the default-on gate
// does not reject the proof DID before receive-pack runs.
cfg.enforce_owner_push = false;
state.config = std::sync::Arc::new(cfg);
state
.db
@@ -6430,6 +6433,9 @@ mod tests {
None,
crate::git::repo_store::build_lock_pool(&pool, 4, std::time::Duration::from_secs(5)),
);
let mut cfg = (*state.config).clone();
cfg.enforce_owner_push = false;
state.config = std::sync::Arc::new(cfg);
state
.db
.upsert_mirror_repo(owner, name, "/tmp/z6succ-sc1", None, false)
@@ -6516,6 +6522,9 @@ mod tests {
let owner = "z6lockpool";
let name = "lp1";
let mut state = crate::test_support::test_state(pool.clone()).await;
let mut cfg = (*state.config).clone();
cfg.enforce_owner_push = false;
state.config = std::sync::Arc::new(cfg);
// One lock-pool connection, short checkout timeout so the exhaustion surfaces
// promptly rather than at the handler's own acquire deadline.
state.repo_store = crate::git::repo_store::RepoStore::new(
+26 -1
View File
@@ -55,7 +55,10 @@ pub struct Config {
#[arg(long, env = "GITLAWB_KEY", default_value = "~/.gitlawb/identity.pem")]
pub key_path: String,
/// Reserved for private-read mode; per-repo read enforcement is not wired in alpha
/// Reserved and currently inert: read access is enforced per repository
/// through `is_public` and path-scoped visibility rules, not this flag.
/// Setting it to false changes nothing; make a repo private through its
/// own visibility instead.
#[arg(long, env = "GITLAWB_PUBLIC_READ", default_value_t = true)]
pub public_read: bool,
@@ -1424,6 +1427,28 @@ mod tests {
);
}
/// #338: GITLAWB_PUBLIC_READ is inert, so its help must not claim read
/// enforcement is missing; it must tell the operator the flag changes
/// nothing and where the real control lives.
#[test]
fn public_read_help_describes_the_flag_as_inert() {
use clap::CommandFactory;
let cmd = Config::command();
let arg = cmd
.get_arguments()
.find(|a| a.get_id() == "public_read")
.expect("the argument must exist");
let help = arg.get_help().map(|h| h.to_string()).unwrap_or_default();
assert!(
!help.contains("not wired"),
"the help still claims read enforcement is unwired: {help}"
);
assert!(
help.contains("inert"),
"the help must say the flag is inert so an operator does not rely on it: {help}"
);
}
/// The flip must not strand an operator mid-upgrade.
///
/// Turning the gate on is a breaking change for any deployment whose pushers are
+1 -1
View File
@@ -110,7 +110,7 @@ async fn main() -> Result<()> {
if !config.public_read {
warn!(
"GITLAWB_PUBLIC_READ=false is reserved; per-repository private-read enforcement is not wired in alpha"
"GITLAWB_PUBLIC_READ=false has no effect; reads are gated per repository by is_public and path-scoped visibility rules, not this flag"
);
}
+1 -1
View File
@@ -60,7 +60,7 @@ pub(crate) async fn run_to_writer(args: WhoamiArgs, w: &mut impl std::io::Write)
}
Ok(resp) => {
let status = resp.status();
let raw = read_body_capped(resp, 8 * 1024).await;
let raw = read_body_capped(resp, 8 * 1024).await.text;
let msg = serde_json::from_str::<Value>(&raw)
.ok()
.and_then(|v| {
+2 -2
View File
@@ -95,7 +95,7 @@ Live-network blockers to prioritize:
- GraphQL POST is still open for compatibility; GraphQL mutations should get mutation-aware auth before it becomes a public write API surface.
- Push authorization is still not capability-complete. A valid DID signature is authentication, not authorization. Owner checks are now enforced on every branch, protected or not (`GITLAWB_ENFORCE_OWNER_PUSH`, on by default); what remains is that a UCAN `git/push` capability is not yet honored, so a delegated or CI key cannot push.
- UCAN chain validation is incomplete and UCAN revocation/blocklisting is not implemented as an operator feature.
- Private repository reads are not enforced. `is_public` and `GITLAWB_PUBLIC_READ` exist, but per-repository private-read behavior is not wired.
- Private repository reads are enforced per repository through `is_public` and path-scoped visibility rules. `GITLAWB_PUBLIC_READ` remains reserved and inert.
- Peer URLs are self-asserted by DIDs. Signatures prove control of the DID key when present, not ownership/safety of the announced URL.
- Outbound peer fetch/ping/sync paths should be reviewed for SSRF protections before accepting arbitrary public peer registrations.
@@ -146,7 +146,7 @@ Risks:
## Obvious live-network priorities
1. Implement repo write authorization: owner checks, UCAN capability checks, and clear delegation semantics for push/PR/issue/bounty operations.
2. Implement private-read enforcement or remove private repo affordances until it exists.
2. Private reads are already enforced per repository (`is_public` plus path-scoped rules); retire the reserved and inert `GITLAWB_PUBLIC_READ` flag or document it as permanently reserved.
3. Add UCAN revocation/blocklisting and operator docs for emergency key compromise.
4. Harden peer registration and outbound fetch behavior against SSRF and peer-list poisoning.
5. Add Docker/installer/release smoke tests to CI.