Parte II — Tronco e radici

05 · Il cerchio: identità e permessi

Ubuntu: "io sono perché noi siamo". In Baobáxia, chi sei vale in tutta la rete; cosa puoi fare vale dentro il cerchio che ti riconosce.

Il cerchio dei ruoli: USER, PAJÉ, OXALÁ

File da leggere

  1. services/auth.py — password (PBKDF2), token JWT, verifica del token di un'altra mucua, freno dei tentativi.
  2. api/v3/auth.py e api/v3/deps.py — il login e come il token diventa il moc che ogni rotta riceve.
  3. infra/identity.py — chiavi Ed25519 (firma) e X25519 (cifratura).
  4. services/permissions.py — can(): ogni decisione di accesso passa da qui.
  5. services/acesso_galaxia.py, services/grupos.py, services/acl.py.
  6. infra/envelope.py — cifratura end-to-end.
  7. services/challenge.py, services/recovery.py, infra/seed_phrase.py.

Due identità, una persona

  • Password (password_hash PBKDF2-SHA256, 200 mila iterazioni) nel saber della mocambola.
  • Chiavi: una coppia Ed25519 (firma paternità e token) + una coppia X25519 (apre saberes cifrati). La privata resta in ~/.baobaxia/keys/<uuid>.json, cifrata con la password (scrypt + AES-GCM), permessi 600 — non viaggia mai. La pubblica va nel saber.bbx.
  • BBX_AUTH_MODE = senha (password) | chave (chiave) | ambos (entrambi, il predefinito).

Login e token

sequenceDiagram
    autonumber
    actor P as Persona
    participant A as POST /auth/login
    participant F as freno (services/auth.py)
    participant S as SaberService
    participant K as identity
    P->>A: username (o nome@uuid8 della mucua) + password
    A->>F: tentativas_bloqueadas?
    alt troppi errori nella finestra
        A-->>P: 429
    end
    A->>S: find_mocambola (preferisce quella della mucua locale)
    A->>A: verify_password (PBKDF2, compare_digest)
    A->>K: cache_session_key — sblocca le private in memoria (8 h)
    A->>A: _issue_for: ruolo effettivo + galassie amministrate
    A->>K: firma un JWT EdDSA con la chiave della MUCUA (o HS256)
    A-->>P: access_token (7 giorni) + profilo senza password_hash

Con il login tramite chiave: POST /auth/desafio restituisce un nonce monouso; POST /auth/login-chave invia la firma (e, se è una chiave secondaria, il certificato di delega firmato dalla principale).

Token firmato da un'altra mucua

flowchart TD
    T[token EdDSA, iss = bbx:mucua:X] --> L{X è la mucua locale?}
    L -- sì --> K[verifica con la chiave che sta SUL DISCO<br/>mai con la pubkey di un saber]
    L -- no --> P[verifica con la pubkey del saber mucua X]
    P --> Q{la mocambola sub è conosciuta qui?}
    Q -- "sì, ed è di un'altra mucua" --> N[rifiuta: X risponde solo<br/>delle proprie mocambola]
    Q -- "sì, ed è di X" --> R[ruolo, galassie e mucua<br/>ricalcolati con i NOSTRI dati]
    Q -- no --> U[entra come USER, senza ambito]

La firma prova chi è; mai cosa può fare qui. (Questo disegno è della versione 3.3 — vedi il modulo 11.)

can(): la decisione

flowchart TD
    A[can mocambola, azione, risorsa] --> S{attore di sistema?}
    S -- sì --> OK[permette]
    S -- no --> R{azione = READ?}
    R -- sì --> RA{bozza?}
    RA -- sì --> RB[solo autore, PAJÉ della mucua,<br/>OXALÁ della galassia]
    RA -- no --> G{galassia riservata<br/>e fuori dalla lista?}
    G -- sì --> NO[nega]
    G -- no --> PR{protecao acl/cifrado?}
    PR -- sì --> PL[lettori, autore;<br/>acl: + PAJÉ della mucua]
    PR -- no --> V[visibility: public → tutti<br/>mucua → stessa mucua o OXALÁ<br/>private → proprietario o PAJÉ]
    R -- no --> W{anonimo?}
    W -- sì --> NO
    W -- no --> RO{galassia in sola lettura?}
    RO -- sì --> NO
    RO -- no --> E[editor del saber UPDATE → gestore locale →<br/>proprietario → PAJÉ della mucua → OXALÁ della galassia]

Il descrittore della risorsa viene costruito in un solo posto (SaberService._descritor / _resource_of). Quando ogni rotta costruiva il proprio, alcune dimenticavano protecao e lasciavano trapelare dati — leggi il docstring di testes/test_vazamentos_de_leitura.py.

Cifratura end-to-end

La zucca sigillata

Con protecao: cifrado, ogni saber riceve una chiave di contenuto (ChaCha20-Poly1305). description, body, location e gli allegati (.bbxenc) vengono cifrati; title e tags restano in chiaro per la ricerca. La chiave del saber viene avvolta per ogni lettore (X25519 ECDH + HKDF + AES-GCM). Il ruolo non apre la zucca: la apre solo chi ha un involucro con il proprio nome.

Recupero

Tre strade indipendenti (services/recovery.py): un guardiano autorizza la rotazione dell'identità (senza mai vedere password né contenuti), una frase seme costruita con risposte personali + entropia, oppure la chiave custodita nella mucua d'origine.

Esercizi

  1. In test_token_federado_recalcula_papel.py, leggi mucua_de_fora_nao_responde_por_mocambola_daqui. Spiega l'attacco con le tue parole.
  2. Crea un saber con protecao: acl e leitores: [qualcuno]. Prova a leggerlo da anonimo tramite l'elenco, il dettaglio, la collezione, il download dell'allegato. (test_vazamentos_de_leitura.py fa proprio questo.)
  3. In permissions.py, qual è la differenza tra acl e cifrado per un PAJÉ? Perché questa differenza è onesta?

Da discutere

  • Il commento di GalaxiaData.acesso (natures/schemas.py) chiama la galassia chiusa "cortesia del software". Cosa significa, e quando basta?
  • Chi dovrebbe essere guardiano dell'identità di qualcuno nella tua comunità?

ver este capítulo como saber