mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-29 09:14:33 +00:00
177 lines
9.8 KiB
Plaintext
177 lines
9.8 KiB
Plaintext
secubox-annuaire (0.2.6-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* feat(#768): P2 config distribution — replica-side 4R apply.
|
|
- annuaire/config_apply.py: apply a signed ConfigBlob (payload carries the
|
|
config TEXT) to <dir>/<scope>.toml through a CSPN 4R double-buffer
|
|
(shadow -> validate content_hash + TOML parse -> atomic swap -> keep
|
|
.sbx-rollback). Idempotent by version; rejects hash-mismatch / unparseable
|
|
without touching the live file. Allowlist + single-writer gating (a node
|
|
never applies a scope it published).
|
|
- annuairectl: `publish-config` (primary publishes a TOML file as a signed,
|
|
versioned blob) and `apply` (replica applies allowed blobs, run as root).
|
|
- +7 tests; suite 177 green.
|
|
|
|
-- Gerald Kerma <devel@cybermind.fr> Tue, 30 Jun 2026 18:30:00 +0200
|
|
|
|
secubox-annuaire (0.2.5-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* fix(#768): correct the satellite-dashboard guard. The 0.2.4 check
|
|
`nginx -T | grep secubox-routes.d` matched config-file *comments*, not real
|
|
includes, so it wrongly removed the API drop-in and re-broke satellite
|
|
dashboards. Replaced with the robust approach: add the route, then let
|
|
`nginx -t` arbitrate — drop it back only if it duplicates a location already
|
|
active in the same (hub) vhost. nginx stays valid either way.
|
|
|
|
-- Gerald Kerma <devel@cybermind.fr> Tue, 30 Jun 2026 17:45:00 +0200
|
|
|
|
secubox-annuaire (0.2.4-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* fix(#768): satellite Annuaire dashboards. The legacy nginx vhost
|
|
(sites-available/secubox) includes secubox.d/ but not secubox-routes.d/, so
|
|
the dashboard's /api/v1/annuaire/ calls fell through to the SPA shell (empty
|
|
UI on non-hub nodes). postinst now drops the API route into secubox.d/ on
|
|
those nodes (idempotent, nginx -t validated, reverted on failure); hub nodes
|
|
whose active config already includes secubox-routes.d are left untouched.
|
|
|
|
-- Gerald Kerma <devel@cybermind.fr> Tue, 30 Jun 2026 17:15:00 +0200
|
|
|
|
secubox-annuaire (0.2.3-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* feat(#768): each node auto-publishes its own NodeRecord on startup.
|
|
The annuaire service (journal owner → no JWT, no write race) reads its mesh
|
|
metadata from secubox-p2p's wg_mesh.json + node.id and publishes a signed
|
|
NodeRecord into the directory, so /nodes lists the actual peers (not just
|
|
replicated offers). Idempotent: skipped when the latest record is unchanged.
|
|
Requires the node identity key from `annuairectl init`; no-op without it.
|
|
+5 tests (read_self_meta, publish-self idempotency); suite 170 green.
|
|
|
|
-- Gerald Kerma <devel@cybermind.fr> Tue, 30 Jun 2026 16:30:00 +0200
|
|
|
|
secubox-annuaire (0.2.2-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* fix(#768): durable wg-mesh nft allow for the :8799 federation listener.
|
|
postinst inserts `iifname wg-mesh ip saddr 10.10.0.0/24 tcp dport 8799
|
|
accept` BEFORE the terminal drop in /etc/nftables.conf on vortex-firewall
|
|
nodes (table inet secubox_filter) so it survives reboot — a rule appended
|
|
after the drop is dead. Idempotent; guarded to mesh nodes; validated with
|
|
`nft -c` and reverted on failure. Legacy `inet filter` hubs (broad 10/8
|
|
accept) are skipped. Closes the cross-node gap where gk2 could not pull a
|
|
peer's /log/export after the peer rebooted.
|
|
|
|
-- Gerald Kerma <devel@cybermind.fr> Tue, 30 Jun 2026 15:30:00 +0200
|
|
|
|
secubox-annuaire (0.2.1-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* feat: gondwana P1 distributed directory, on top of #766 (#768)
|
|
- model: NodeRecord (signed mesh peer registry, public wg key only) +
|
|
ConfigBlob (signed, versioned, single-writer config) + Op NODE_PUBLISH /
|
|
CONFIG_PUBLISH / CONFIG_REVOKE. Coexists with #766's Op.GENESIS.
|
|
- verbs: publish_node / publish_config / revoke_config + _get_nodes /
|
|
_get_configs (last-writer-wins by version → convergent across the mesh);
|
|
ingest_config; export_entries / import_entries generic log federation
|
|
(dedup by (author,sig), self-certifying binding + sig verified before
|
|
append — same defense #766 added to ingest_offer, generalized to the
|
|
whole log). resolver: config.publish right (MEMBER).
|
|
- api: GET /nodes, /config, /log/export; POST /node/publish,
|
|
/config/publish, /config/revoke, /log/pull.
|
|
- mesh_sync: in-process replication loop (the annuaire service owns the
|
|
journal → no JWT, no write race) pulling each peer's /log/export from the
|
|
#766 Gondwana mesh listener (wg-mesh-ip:8799). ANNUAIRE_DIR_SYNC=0
|
|
disables. secubox-p2p stays the peer-list owner (wg_mesh.json).
|
|
- nginx/annuaire-mesh.conf.tpl: the mesh listener now also serves
|
|
GET /log/export (signed, self-certifying, read-only) for replication —
|
|
not just /services.
|
|
- node identity reuses #766's genesis()/annuairectl/node.key (no new key
|
|
path invented). 40 directory/sync tests; full suite 167 green.
|
|
|
|
-- Gerald Kerma <devel@cybermind.fr> Tue, 30 Jun 2026 14:30:00 +0200
|
|
|
|
secubox-annuaire (0.2.0-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* feat: trustless cross-node service federation (#766)
|
|
- ingest_offer now enforces the self-certifying binding
|
|
did_from_pubkey(pubkey) == offer.provider BEFORE checking the signature.
|
|
Closes the "bring your own key, claim any provider DID" forgery: the sig
|
|
alone only proves key-ownership, not that the key belongs to the claimed
|
|
provider. did:plc is sha256(pubkey)[:32], so the check needs no directory
|
|
and no prior trust in the provider.
|
|
- _get_offers / GET /services now emit self-contained, verifiable offers:
|
|
the stored payload omits sig/signer_did (not part of the signed bytes) and
|
|
never carried the pubkey, so a stranger could not verify at all. Offers now
|
|
carry sig + signer_did + provider_pubkey (transport metadata, stripped
|
|
before model reconstruction — ServiceOffer is extra=forbid).
|
|
- pull_services uses the carried provider_pubkey and feeds the now
|
|
self-certifying ingest_offer.
|
|
* feat: node bootstrap — genesis() verb + annuairectl CLI.
|
|
- genesis(): a node self-attests as a founding MEMBER (root of trust),
|
|
breaking the invite/join/subscribe chicken-and-egg. Self-certifying DID,
|
|
empty invited_by (never inflates emancipation plurality), idempotent.
|
|
- Op.GENESIS added (additive, chain-compatible).
|
|
- crypto.public_from_private(): derive pubkey from the persisted private key.
|
|
- /usr/sbin/annuairectl: init | whoami | status | offer | services | pull.
|
|
Operates the journal directly as the secubox user (no JWT for the one-time
|
|
privileged bootstrap); node key persisted 0600 in
|
|
/etc/secubox/secrets/annuaire/node.key.
|
|
* feat: Gondwana mesh federation listener (postinst-rendered).
|
|
- nginx/annuaire-mesh.conf.tpl: binds ONLY the node wg-mesh IPv4:8799,
|
|
allow 10.10.0.0/24 + deny all, exposes ONLY GET /api/v1/annuaire/services.
|
|
postinst substitutes the detected wg-mesh IP; skips install when no mesh
|
|
interface exists. postrm removes it on uninstall.
|
|
* tests: +7 federation tests (genesis member/idempotent, offer enrichment,
|
|
trustless round-trip pull, forged-pubkey + tampered-payload + bad-hex
|
|
rejection). 134 passing.
|
|
* hardening (security review): postinst validates the rendered mesh listener
|
|
with `nginx -t` and reverts it on failure so a broken render can never
|
|
persist (board-wide nginx blast radius); ship
|
|
/etc/sysctl.d/30-secubox-nonlocal-bind.conf (net.ipv4.ip_nonlocal_bind=1)
|
|
so nginx can bind the wg-mesh IP even if wg-quick@wg-mesh starts after
|
|
nginx at boot.
|
|
|
|
-- Gerald Kerma <devel@cybermind.fr> Tue, 30 Jun 2026 16:00:00 +0200
|
|
|
|
secubox-annuaire (0.1.3-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* feat: service offers + subscription verbs, API and UI + pull federation
|
|
- annuaire/verbs.py: offer_service, revoke_offer, subscribe,
|
|
approve_subscription, reject_subscription, ingest_offer,
|
|
subscription_state, _get_offers, _get_offer helpers.
|
|
- api/main.py: GET /services, POST /service/offer,
|
|
POST /service/{id}/revoke, POST /service/{id}/subscribe,
|
|
GET /subscriptions, POST /subscription/{id}/approve,
|
|
POST /subscription/{id}/reject, POST /services/pull.
|
|
- www/annuaire/index.html: Services section + My subscriptions panel.
|
|
- tests/test_services.py: 28 new tests covering all security invariants.
|
|
|
|
-- Gerald KERMA <devel@cybermind.fr> Tue, 30 Jun 2026 12:00:00 +0200
|
|
|
|
secubox-annuaire (0.1.2-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* ui: minimal shared-template dashboard (chain integrity, merkle root,
|
|
trust log) at /annuaire/ — also makes the module appear in the navbar.
|
|
|
|
-- Gerald KERMA <devel@cybermind.fr> Tue, 30 Jun 2026 09:30:00 +0200
|
|
|
|
secubox-annuaire (0.1.1-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* security: enforce self-certifying authorship at read time (an Identity
|
|
entry only sets state for its own did:author); authorize revocation (only
|
|
self or the grafting inviter), derive REVOKED from the signed
|
|
RevocationNotice (no victim-identity forging); staged single-step
|
|
emancipation with a required founder_did. +7 adversarial tests.
|
|
|
|
-- Gerald KERMA <devel@cybermind.fr> Tue, 30 Jun 2026 09:00:00 +0200
|
|
|
|
secubox-annuaire (0.1.0-1~bookworm1) bookworm; urgency=medium
|
|
|
|
* Initial release — Annuaire-Miroir trust substrate.
|
|
- annuaire/verbs.py: auto_add / invite / accept_invite / propose / vote /
|
|
tally / revoke / emancipate — the four protocols from spec §3.
|
|
- annuaire/model.py, crypto.py, log.py, resolver.py: BLAKE2b-chained
|
|
SQLite-WAL journal + Ed25519 signing + can() resolver (pre-existing core).
|
|
- api/main.py: FastAPI on /run/secubox/annuaire.sock, JWT-gated mutating
|
|
endpoints; read endpoints public.
|
|
- Packaging: secubox-annuaire.service (User=secubox, RuntimeDirectoryPreserve=yes,
|
|
NoNewPrivileges=yes), nginx routes + static conf, menu.d, secubox.yaml.
|
|
|
|
-- Gerald KERMA <devel@cybermind.fr> Mon, 30 Jun 2026 08:00:00 +0200
|