Changeset f63cbc2 in Klonkt for src/routes


Ignore:
Timestamp:
06/16/2026 06:33:38 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
4fee228
Parents:
1b4d5dd
Message:

Circles: protocol version enforced via signature binding (update enforcement)

KLONKT_PROTO is now part of the signed basis (signingInput:
"klonkt/proto/N\n"+body). An instance on a different proto cannot verify
the signed outbox and vice versa → staying up to date is cryptographically
enforced, not a patchable check. Both sides verify the proto
(actor.klonkt.proto + Klonkt-Proto header → 426); too-old/too-new sources
are excluded with status 'outdated' + a clear message. Couple security to
every proto bump. Proto starts at 2; roll out in lockstep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/federation.js

    r1b4d5dd rf63cbc2  
    88
    99import express from 'express';
    10 import { buildActor, buildOutbox, signBody } from '../services/CircleFederation.js';
     10import { buildActor, buildOutbox, signBody, KLONKT_PROTO, MIN_PROTO } from '../services/CircleFederation.js';
    1111import { getTenancy } from '../services/SettingsService.js';
    1212
     
    1818}
    1919
     20// De proto die de consument zegt te draaien (uit z'n request-header), of 0.
     21function consumerProto(req) {
     22  return parseInt(req.get('Klonkt-Proto') || '0', 10) || 0;
     23}
     24
    2025router.get('/.klonkt/actor.json', (req, res) => {
    2126  // Cirkels = solo-naar-solo; hubs publiceren geen federatie-actor.
    2227  if (getTenancy() === 'hub') return res.status(404).type('text/plain').send('Niet beschikbaar in hub-modus');
     28  // De actor serveren we ALTIJD (ook aan oudere consumenten) zodat zij onze proto
     29  // kunnen lezen en een nette "update vereist"-melding kunnen tonen.
    2330  const body = JSON.stringify(buildActor(baseUrl(req)), null, 2);
    2431  res.type('application/activity+json; charset=utf-8');
     32  res.set('Klonkt-Proto', String(KLONKT_PROTO));
    2533  res.set('Cache-Control', 'public, max-age=300');
    2634  res.send(body);
     
    2937router.get('/.klonkt/outbox.json', (req, res) => {
    3038  if (getTenancy() === 'hub') return res.status(404).type('text/plain').send('Niet beschikbaar in hub-modus');
     39  res.set('Klonkt-Proto', String(KLONKT_PROTO));
     40  // Te-oude consument? Weiger met 426 Upgrade Required (de crypto-binding sluit 'm
     41  // sowieso al uit; dit geeft een expliciet, leesbaar signaal). proto 0 = geen
     42  // header (bv. een browser/curl) → toestaan, die verifieert toch niet.
     43  const cp = consumerProto(req);
     44  if (cp && cp < MIN_PROTO) {
     45    return res.status(426).type('text/plain')
     46      .send(`Upgrade Required: deze cirkel draait proto ${KLONKT_PROTO}; jouw Klonkt (proto ${cp}) is te oud.`);
     47  }
    3148  const body = JSON.stringify(buildOutbox(baseUrl(req)), null, 2);
    3249  res.type('application/activity+json; charset=utf-8');
Note: See TracChangeset for help on using the changeset viewer.