Skip to content

Commit e8992d6

Browse files
MaxBrychclaude
andcommitted
feat(manifest): Röbel declares its agentic workspace — buzz.roebel.app, pinned sha-3e48f1b, Max as owner, Mecky as member
Owner = MaxBrych's public kind-0 author key (already on the world-readable record); agent member = Mecky's declared relay pubkey. Baseline tests learn that the canonical manifest now carries buzz. B-track B0.3 (manifest half). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent ec62ed2 commit e8992d6

3 files changed

Lines changed: 41 additions & 9 deletions

File tree

packages/cli/test/doctor.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ test("a declared buzz workspace is an endpoint, counts for comms, and nags about
175175
};
176176
assert.ok(!doctor(withAgents).warnings.some((w) => w.includes("buzz declared without")));
177177

178-
// Undeclared -> no buzz endpoint, comms note unchanged.
179-
const plain = doctor(roebel);
178+
// Undeclared -> no buzz endpoint, comms note unchanged. (The canonical
179+
// manifest now declares buzz, so strip it for the baseline.)
180+
const { buzz: _buzz, ...servicesWithoutBuzz } = roebel.services;
181+
const plain = doctor({ ...roebel, services: servicesWithoutBuzz });
180182
assert.ok(!plain.endpoints.some((e) => e.name === "buzz"));
181183
assert.doesNotMatch(plain.sovereignty.find((l) => l.layer === "comms")!.note, /workspace relay/);
182184
});

packages/cli/test/render.test.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,12 @@ test("secrets appear only as references, never resolved values", () => {
8080
// every secret the manifest names is surfaced as a ref in SECRETS.md
8181
assert.deepEqual(
8282
collectSecretRefs(roebel).sort(),
83-
["$COORDINATOR_PUBKEY", "$GNOSIS_BUNDLER_RPC", "$GNOSIS_RPC", "$MATRIX_CLIENT_SECRET", "$NEXTCLOUD_CLIENT_SECRET", "$ROEBEL_ID_JWKS", "$SUPABASE_URL", "$WEB_CLIENT_SECRET"],
83+
[
84+
"$BUZZ_GIT_HOOK_HMAC_SECRET", "$BUZZ_POSTGRES_PASSWORD", "$BUZZ_REDIS_PASSWORD",
85+
"$BUZZ_RELAY_PRIVATE_KEY", "$BUZZ_S3_ACCESS_KEY", "$BUZZ_S3_SECRET_KEY",
86+
"$COORDINATOR_PUBKEY", "$GNOSIS_BUNDLER_RPC", "$GNOSIS_RPC", "$MATRIX_CLIENT_SECRET",
87+
"$NEXTCLOUD_CLIENT_SECRET", "$ROEBEL_ID_JWKS", "$SUPABASE_URL", "$WEB_CLIENT_SECRET",
88+
],
8489
);
8590
// the keystone env references the secret, it does not inline a value
8691
assert.match(renderBundle(selfHosted).files["roebel-id.env"], /NEXTCLOUD_CLIENT_SECRET=\$NEXTCLOUD_CLIENT_SECRET/);
@@ -95,7 +100,7 @@ test("the plan is ordered and covers every declared surface", () => {
95100
// Federation follows the relay: peers are mirrored into a store that only
96101
// exists once the node's own Nostr surface is up.
97102
// The indexer follows the relay: it indexes stores that must exist first.
98-
"mas-oidc", "nostr-relay", "indexer", "federation", "web-env",
103+
"mas-oidc", "nostr-relay", "buzz", "indexer", "federation", "web-env",
99104
// Operations come after the services exist but before "verify" — a node is
100105
// not verified until it is also survivable.
101106
"backup", "backup-offsite", "backup-restore-test", "harden", "firewall",
@@ -581,11 +586,15 @@ test("manifest-declared agent keys become the add-members script; humans-only sh
581586
});
582587

583588
test("buzz is config-gated — an undeclared workspace changes nothing", () => {
584-
const compose = renderComposeYml(roebel);
589+
// The canonical Röbel manifest now declares buzz, so the baseline is a
590+
// variant with it stripped — the assertion stays: no declaration, no trace.
591+
const { buzz: _buzz, ...servicesWithoutBuzz } = roebel.services;
592+
const noBuzz = { ...roebel, services: servicesWithoutBuzz };
593+
const compose = renderComposeYml(noBuzz);
585594
assert.doesNotMatch(compose, /buzz/i);
586-
assert.doesNotMatch(renderCaddyfile(roebel), /buzz/i);
587-
assert.equal(renderBundle(roebel).files["buzz/add-members.sh"], undefined);
588-
assert.ok(!plan(roebel).some((s) => s.id === "buzz"));
595+
assert.doesNotMatch(renderCaddyfile(noBuzz), /buzz/i);
596+
assert.equal(renderBundle(noBuzz).files["buzz/add-members.sh"], undefined);
597+
assert.ok(!plan(noBuzz).some((s) => s.id === "buzz"));
589598
});
590599

591600
test("a vault: secret ref fails at render time, not on the box", () => {

packages/protocol/examples/roebel.netizen.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@
167167
"element": "https://chat.roebel.app"
168168
}
169169
},
170+
"buzz": {
171+
"url": "https://buzz.roebel.app",
172+
"imageTag": "sha-3e48f1b",
173+
"ownerPubkey": "4dbcf5811b976212623b75f778e3be404643eb2f200bbb8ac8ebf6f46fecac0a",
174+
"agentPubkeys": [
175+
"412e639ad250e84faeb3033bba1d20ee09b8a68a2ca8542fcd19d3c2475df16b"
176+
],
177+
"secrets": {
178+
"postgresPassword": "$BUZZ_POSTGRES_PASSWORD",
179+
"redisPassword": "$BUZZ_REDIS_PASSWORD",
180+
"s3AccessKey": "$BUZZ_S3_ACCESS_KEY",
181+
"s3SecretKey": "$BUZZ_S3_SECRET_KEY",
182+
"relayPrivateKey": "$BUZZ_RELAY_PRIVATE_KEY",
183+
"gitHookHmac": "$BUZZ_GIT_HOOK_HMAC_SECRET"
184+
}
185+
},
170186
"secrets": {
171187
"nextcloudClientSecret": "$NEXTCLOUD_CLIENT_SECRET",
172188
"matrixClientSecret": "$MATRIX_CLIENT_SECRET",
@@ -296,7 +312,12 @@
296312
],
297313
"record": {
298314
"decisions": {
299-
"bodies": [{ "id": "stadtvertretung", "noticeScope": "town" }]
315+
"bodies": [
316+
{
317+
"id": "stadtvertretung",
318+
"noticeScope": "town"
319+
}
320+
]
300321
}
301322
},
302323
"branding": {

0 commit comments

Comments
 (0)