Skip to content

fix: add org revocation CLI#131

Merged
igorls merged 5 commits into
mainfrom
codex/add-org-revoke-cli
Jul 6, 2026
Merged

fix: add org revocation CLI#131
igorls merged 5 commits into
mainfrom
codex/add-org-revoke-cli

Conversation

@igorls

@igorls igorls commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add meshguard org-revoke <node-key-or-path> [--reason <reason>] to create signed OrgCertRevoke messages from the local org keypair.
  • Persist revocations as encoded 0x42 wire messages under $MESHGUARD_CONFIG_DIR/revoked/*.revoke and queue them for best-effort SWIM control-plane broadcast on meshguard up.
  • Retain verified signed revocations in memory for duplicate-suppressed periodic re-broadcast, so peers that learn a revocation can propagate it onward.
  • Add org revocation helpers/tests and update CLI/trust/security docs to remove the missing-tooling caveat.

Closes #126

Validation

  • zig build test --summary all (110/110)
  • zig build --summary all
  • Windows CLI smoke with isolated MESHGUARD_CONFIG_DIR: keygen, org-keygen, org-revoke --reason key-compromised, verified one 138-byte .revoke artifact and config show pending revocation output
  • zig build -Dtarget=x86_64-linux-gnu -Dno-sodium=true --summary all
  • zig build -Dtarget=x86_64-macos -Doptimize=ReleaseFast --summary all
  • zig build -Dtarget=x86_64-freebsd -Doptimize=ReleaseFast --summary all
  • git diff --check

Copilot AI review requested due to automatic review settings July 5, 2026 19:44

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 114fe83247

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/discovery/swim.zig

fn enqueueOrgControl(self: *SwimProtocol, data: []const u8) void {
if (data.len > Org.ORG_REVOKE_WIRE_SIZE) return;
if (self.org_control_count >= self.org_control_queue.len) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle revocations past the queue capacity

When $MESHGUARD_CONFIG_DIR/revoked/ contains more than 16 .revoke files, loadOrgRevocations can return up to 64 entries and loadPendingOrgRevocations iterates all of them, but this guard silently drops every entry after org_control_queue fills. Those dropped signed revocations are still reported as pending but are never broadcast during that meshguard up, so fleets with more than 16 revoked org certs leave the later revocations unenforced on other peers. Consider retaining/retrying overflow entries or matching the queue capacity to the loader capacity instead of returning silently.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds first-class CLI support for creating and propagating signed org certificate revocations (OrgCertRevoke), filling the tooling gap described in #126 and aligning docs with the now-implemented workflow.

Changes:

  • Add meshguard org-revoke <node-key-or-path> [--reason <reason>] to sign and persist org revocations under $MESHGUARD_CONFIG_DIR/revoked/*.revoke.
  • Load pending revocations on meshguard up and queue them for best-effort SWIM broadcast (and local application when authorized).
  • Add org revocation helpers + tests, and update CLI/trust/security documentation to remove the “missing tooling” caveat.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/main.zig Adds org-revoke command, queues pending revocations on up, and shows pending revocations in config show.
src/identity/org.zig Introduces org revocation helpers (reason parsing, signing, save/load, tests).
src/discovery/swim.zig Adds an org-control broadcast queue and applies queued revocations locally when authorized.
docs/reference/cli.md Documents the new meshguard org-revoke command and its behavior.
docs/guide/trust-model.md Updates trust model guidance to include org revoke workflow.
docs/concepts/security.md Updates security overview to reference org-revoke as revocation tooling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/identity/org.zig
Comment thread src/main.zig Outdated
Comment on lines +4486 to +4504
// ─── Org Revocations ───
const revoke_dir = std.fs.path.join(allocator, &.{ config_dir, "revoked" }) catch null;
defer if (revoke_dir) |rd| allocator.free(rd);

if (revoke_dir) |rd| {
if (std.Io.Dir.openDirAbsolute(zio(), rd, .{ .iterate = true })) |dir| {
defer dir.close(zio());
var revoke_count: usize = 0;
var iter = dir.iterate();
while (iter.next(zio()) catch null) |entry| {
if (std.mem.endsWith(u8, entry.name, ".revoke")) revoke_count += 1;
}
if (revoke_count > 0) {
try stdout.writeStreamingAll(zio(), "\n");
try writeFormatted(stdout, "\x1b[1m─── Org Revocations ({d}) ───────────────────────\x1b[0m\n", .{revoke_count});
try writeFormatted(stdout, " {d} pending revocation(s)\n", .{revoke_count});
}
} else |_| {}
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc7f5554ef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/discovery/swim.zig Outdated
while (iter.next()) |entry| {
if (entry.value_ptr.state == .dead) continue;
const ep = entry.value_ptr.gossip_endpoint orelse continue;
self.gossipSend(slot.data[0..slot.len], ep);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Re-gossip verified org revocations

This drains locally loaded .revoke files by sending the raw control message only from this node, while handleOrgRevoke only updates the in-memory revoked_nodes set and never re-enqueues or persists a verified revocation. If the revoker's membership view is incomplete during the few broadcast ticks (for example just after meshguard up through a seed, after a partition, or for peers that restart/join after the queue expires), peers only reachable through recipients never learn the revocation and can still accept the revoked org cert. Please re-broadcast verified revokes with duplicate suppression, or carry/persist them through the existing gossip path.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 030a2c3ce8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/discovery/swim.zig Outdated
Comment on lines +1447 to +1451
self.gossipSend(slot.data[0..slot.len], ep);
sent_any = true;
}

if (sent_any) slot.remaining -|= 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep revokes queued when fan-out sends are dropped

In meshes where pending revokes times alive peers exceeds the send token bucket, gossipSend silently drops over-budget packets but this loop still sets sent_any and consumes a retry for the slot. Because the slot/peer iteration order is stable, the same early sends can consume the available tokens on each retry/readvertise while later peers repeatedly miss the revocation, leaving them accepting the revoked org cert. Have gossipSend report actual success or track per-peer progress before decrementing remaining.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6917e4dc4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/discovery/swim.zig
self.rememberOrgRevoke(rev);
self.enqueueOrgRevokeBroadcast(rev);
if (self.isOrgAuthorizedPeer(rev.org_pubkey)) {
self.applyOrgRevoke(rev, false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope org revokes to the issuing org

When a node trusts multiple orgs, this applies any queued revoke from a trusted org to applyOrgRevoke, which records only rev.node_pubkey in the global revoked_nodes set; certAuthorizesPeer/recordedCertAuthorizesPeer then reject that pubkey even when its cert was issued by a different trusted org. With the new org-revoke broadcast path, an admin of org A can therefore evict nodes that are members of org B. Store revocations by (org_pubkey, node_pubkey) and compare them with the certificate/vouch issuer before rejecting.

Useful? React with 👍 / 👎.

@igorls igorls merged commit 6a44d4a into main Jul 6, 2026
5 checks passed
@igorls igorls deleted the codex/add-org-revoke-cli branch July 6, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CLI tooling for signed org certificate revocation

2 participants