Manyleb Protocol qub

Mae qub yn brotocol ar gyfer ymrwymiadau amserol cryptograffig: system ar gyfer selio geiriau i ddyddiad yn y dyfodol a phrofi, pan fydd y dyddiad hwnnw'n cyrraedd, yn union beth a ddywedwyd a phryd.

Mae tri phrimitif yn gwneud i hyn weithio. Mae drand yn oleudy hap datganoledig — mae'r dyddiad datgelu yn orfodadwy gan ffiseg, nid gan ewyllys da unrhyw barti. Mae storfa gyhoeddus barhaol yn storfa gyhoeddus gwrth-ymyrryd — ni all unrhyw barti olygu na dileu qub unwaith y mae wedi'i selio. Mae ML-DSA-65 yn lofnod digidol ôl-gwantwm — mae pob qub wedi'i glymu wrth bâr o allweddi nad yw eu cyfrinach byth yn gadael dyfais yr awdur.

Gyda'i gilydd, mae'r primitifau hyn yn gwneud datganiad sydd wedi'i gloi-amser, yn dystiolaeth o ymyrraeth, ac yn briodoladwy — derbynneb y mae ei gwerth yn tyfu wrth i allu'r byd i ffugio'r gorffennol wella.

Mae gweddill y ddogfen hon yn fanyleb normadol sy'n ofynnol ar gyfer gweithrediadau rhyngweithredadwy.


Manyleb Protocol qub

Maes Gwerth
Fersiwn 1.0 (fersiwn protocol 0x01, fersiwn amlapio allanol 0x01)
Dyddiad 2026-05-01
Statws Drafft
Adolygwyd hyd at 2026-05-01

Y ddogfen hon yw'r fanyleb protocol normadol ar gyfer system ymrwymiad amserol qub. Mae'n diffinio strwythurau data, rheolau cyfresoli, fformiwlâu deilliad, a gweithdrefnau dilysu sy'n ofynnol ar gyfer gweithrediadau rhyngweithredadwy.

Cwmpas: mae haen y protocol yn fwriadol-niwtral o ran iaith — bytes plaen / markdown / cytundeb yw corff y qub yn ddi-ddehongli, ac mae rendro ymwybodol-o-leoliad yn gyfrifoldeb y gwyliwr (ap gwe qub.social, iframe <qub-embed>, cleientiaid MCP, ac ati).


1. Nodiant a Chonfensiynau

Nodiant Ystyr
u8, u64, i64 Cyfanrifau anarwyddedig/arwyddedig o led bit penodol
[u8; N] Arae byte o hyd sefydlog N bytes
Vec<u8> Arae byte o hyd amrywiol
Option<T> Gwerth o fath T, neu absennol
String Llinyn testun UTF-8, wedi'i normaleiddio NFC
`
SHA3-256(x) Hash NIST SHA3-256 o linyn byte x (FIPS 202)
ceil(x) Swyddogaeth nenfwd: cyfanrif lleiaf ≥ x
CBOR Concise Binary Object Representation (RFC 8949)
big-endian Y byte mwyaf arwyddocaol yn gyntaf

Mae pob cyfanrif mewn strwythurau preimage wedi'u hamgodio fel araeau byte big-endian o led sefydlog (i64 → 8 byte, u8 → 1 byte) oni nodir fel arall.

Mae pob amserlin yn eiliadau Unix yn UTC.


2. Strwythurau Data

2.1 ComposeQub (Cyflwr Yn-Cof y Crëwr)

Heb ei gyfresoli i CBOR. Heb ei ysgrifennu i storfa parhaol. Lleol i ap y crëwr.

ComposeQub {
    draft_id:       [u8; 16],        // Random, generated locally
    created_at:     i64,             // Unix seconds UTC
    unlock_at:      Option<i64>,     // Unix seconds UTC; None while composing
    visibility:     u8,              // 0x01 = public (only value in MVP)
    content_type:   u8,              // 0x01 = text (only value in MVP)
    plaintext:      Vec<u8>,         // UTF-8 qub body
    sender_label:   Option<String>,  // Decorative display name; not authenticated
    status:         DraftStatus,     // Composing | Sealed | Uploaded | Failed
}

2.2 QubEnvelope (Llwyth Tâl wedi'i Ddatgryptio)

Wedi'i gyfresoli gan ddefnyddio CBOR safonol (§3). Wedi'i amgryptio y tu mewn i'r SealedQub. Dyma'r strwythur sy'n profi cywirdeb cynnwys ar ôl datgryptio.

QubEnvelope {
    version:             u8,              // Protocol major version (0x01 for v1)
    qub_id:              [u8; 32],        // Derived (see §4.1)
    content_type:        u8,              // Content type registry (see §6)
    created_at:          i64,             // Unix seconds UTC
    unlock_at:           i64,             // Unix seconds UTC
    outcome_at:          Option<i64>,     // V1.1 — pan fydd realiti'n cynnig dyfarniad (verdict-uplift-plan §3.1)
    sender_label:        Option<String>,  // Decorative; not authenticated in MVP
    reply_to:            Option<[u8; 32]>,// Parent qub_id for reply chains; not in qub_id preimage; not signed (see §9.3)
    body:                Vec<u8>,         // Content payload (UTF-8 for text, CBOR for pact)
    body_hash:           [u8; 32],        // SHA3-256(body) (see §4.2)
    sig_alg:             u8,              // Signature algorithm (see §9.2)
    author_signature:    Option<Vec<u8>>, // Set when sig_alg != 0x00
    author_pubkey:       Option<Vec<u8>>, // Set when sig_alg != 0x00
    cosigner_pubkey:     Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
    cosigner_signature:  Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
}

Sylfaen (qub testun heb ei lofnodi): version = 0x01, content_type = 0x01, sig_alg = 0x00, pob maes Option yn absennol.

Cyfluniadau v1 eraill: content_type = 0x03 (corff cytundeb, gweler §6.1); sig_alg = 0x01 (ML-DSA-65) gydag author_signature ac author_pubkey yn bresennol (gweler §9.3); cosigner_pubkey a cosigner_signature yn bresennol gyda'i gilydd ar gyfer cytundebau wedi'u cyd-arwyddo (gweler §9.7); reply_to wedi'i osod i qub_id y qub rhiant ar gyfer qubs cadwyn-ateb (gweler §9.3 am oblygiadau cwmpas y llofnod).

2.3 SealedQub (Fformat Gwifren Safonol)

Wedi'i gyfresoli gan ddefnyddio CBOR safonol (§3). Wedi'i ysgrifennu i storfa parhaol. Dyma'r arteffact ar-y-gadwyn.

SealedQub {
    version:           u8,              // Protocol major version (0x01 for v1)
    qub_id:            [u8; 32],        // Same as QubEnvelope.qub_id
    visibility:        u8,              // 0x01 = public; v1 viewers reject other values
    unlock_at:         i64,             // Unix seconds UTC
    outcome_at:        Option<i64>,     // V1.1 — yn ymddangos ar y CTA gwylio-dyfarniad
                                        //   cyn datgelu; yn adlewyrchu QubEnvelope.outcome_at;
                                        //   wedi'i rwymo i qub_id trwy preimage §4.1.
    drand_chain_id:    String,          // drand chain hash (hex string)
    drand_round:       u64,             // Target drand round number
    tlock_ciphertext:  Vec<u8>,         // tlock-encrypted QubEnvelope CBOR bytes
    recipient_pubkey:  Option<[u8; 32]>,// Reserved field; accepted by canonical CBOR
                                        //   but not interpreted by the v1 reference viewer
    title:             Option<String>,  // Plaintext title surfaced on the viewer
                                        //   countdown before reveal. Bound to qub_id
                                        //   via title_hash (§4.1). 1..=100 NFC code
                                        //   points, no control characters.
}

2.4 RevealedQub (Cyflwr Cymhwysiad y Gwyliwr)

Heb ei gyfresoli i CBOR. Lleol i ap y gwyliwr. Adeiladwyd ar ôl datgryptio a dilysu llwyddiannus.

RevealedQub {
    qub_id:              [u8; 32],
    arweave_tx_id:       String,
    visibility:          u8,
    content_type:        u8,
    created_at:          i64,
    unlock_at:           i64,
    outcome_at:          Option<i64>,       // V1.1 — wedi'i gario ymlaen o QubEnvelope.outcome_at / SealedQub.outcome_at; yn gyrru bloc gwylio-dyfarniad tudalen y datgeliad (verdict-uplift-plan §5.1)
    drand_chain_id:      String,
    drand_round:         u64,
    sender_label:        Option<String>,
    title:               Option<String>,    // Carried forward from SealedQub.title
    reply_to:            Option<[u8; 32]>,
    body:                Vec<u8>,
    body_hash:           [u8; 32],
    body_hash_verified:  bool,
    author_signature:    Option<Vec<u8>>,
    author_pubkey:       Option<Vec<u8>>,
    signature_verified:  Option<bool>,
    cosigner_pubkey:     Option<Vec<u8>>,
    cosigner_signature:  Option<Vec<u8>>,
    cosigner_verified:   Option<bool>,
}

3. Proffil CBOR Safonol

RHAID i bob cyfresoli SealedQub a QubEnvelope gydymffurfio â'r proffil hwn. RHAID i ddau weithrediad sy'n derbyn yr un strwythur rhesymegol gynhyrchu bytes union yr un fath.

3.1 Rheolau Amgodio

Rheol Manyleb
Safon RFC 8949 §4.2.1 (Core Deterministic Encoding Requirements)
Trefnu allweddi map Wedi'i drefnu yn ôl hyd byte wedi'i amgodio yn gyntaf (byrrach cyn hwy), yna'n lecsicograffig (byte-wrth-byte ar gyfer amgodiadau o'r un hyd)
Amgodio cyfanrifau Y ffurf fyrraf: 0–23 yn y byte cychwynnol; 24–255 mewn 2 byte; 256–65535 mewn 3 byte; ac ati.
Amgodio hyd Hyd pendant yn unig. Dim araeau, mapiau, llinynnau byte, na llinynnau testun o hyd amhendant (gwybodaeth ychwanegol = 31 wedi'i gwahardd).
Tagiau Dim tagiau CBOR (math mawr 6 wedi'i wahardd).
Pwynt-arnofiol Dim arnofiolion (gwerthoedd math mawr 7 0xF9–0xFB wedi'u gwahardd).
Llinynnau testun UTF-8 wedi'i amgodio, wedi'i normaleiddio NFC (Ffurflen Normaleiddio Unicode C).
Llinynnau byte Bytes amrwd. Dim amgodio base64 yn yr haen CBOR.
Allweddi dyblyg Gwrthod gyda gwall. RHAID i barseyddion BEIDIO â derbyn allweddi map dyblyg yn dawel.
Gwerthoedd syml Dim ond true (0xF5), false (0xF4), a null (0xF6) a ganiateir.
Meysydd dewisol Mae meysydd dewisol absennol yn cael eu hepgor yn llwyr o'r map CBOR (heb eu hamgodio fel null). Mae meysydd dewisol presennol yn cael eu cynnwys yn nhrefn allweddi wedi'i didoli.

3.2 Trefn Allweddi Safonol wedi'u Dilysu

Mae'r trefnau allweddi hyn yn normadol. RHAID i weithrediadau allyrru allweddi yn union y drefn hon. DYLAI haeriadau dadfygio ddilysu trefnu mewn adeiladau di-ryddhad.

QubEnvelope (fersiwn 0x01, heb ei lofnodi, pob maes dewisol yn absennol):

"body"                (5 encoded bytes)
"qub_id"              (7 encoded bytes)
"sig_alg"             (8 encoded bytes)
"version"             (8 encoded bytes)
"reply_to"            (9 encoded bytes)   ← only if present (reply chains)
"body_hash"           (10 encoded bytes)
"unlock_at"           (10 encoded bytes)
"created_at"          (11 encoded bytes)
"outcome_at"          (11 encoded bytes)  ← only if present (V1.1 verdict mechanic)
"content_type"        (13 encoded bytes)
"sender_label"        (13 encoded bytes)  ← only if present
"author_pubkey"       (14 encoded bytes)  ← only if present
"cosigner_pubkey"     (16 encoded bytes)  ← only if present (pact cosign)
"author_signature"    (17 encoded bytes)  ← only if present
"cosigner_signature"  (19 encoded bytes)  ← only if present (pact cosign)

Deilliad trefn allwedd QubEnvelope: mae pob allwedd yn llinyn testun CBOR. Hyd amgodedig = pennawd 1 byte + hyd y llinyn (ar gyfer llinynnau o dan 24 byte). Trefnwch yn ôl cyfanswm hyd amgodedig yn gyntaf, yna'n lecsicograffig ar gyfer allweddi o'r un hyd.

SealedQub (fersiwn 0x01, cyhoeddus, dim derbynnydd):

"title"             (6 encoded bytes)   ← only if present
"qub_id"            (7 encoded bytes)
"version"           (8 encoded bytes)
"unlock_at"         (10 encoded bytes)
"outcome_at"        (11 encoded bytes)  ← only if present (V1.1 verdict mechanic)
"visibility"        (11 encoded bytes)
"drand_round"       (12 encoded bytes)
"drand_chain_id"    (15 encoded bytes)
"recipient_pubkey"  (17 encoded bytes)  ← only if present
"tlock_ciphertext"  (17 encoded bytes)

PactTerms (corff cytundeb, content_type 0x03):

"notes"         (6 encoded bytes)  ← only if present
"terms"         (6 encoded bytes)
"title"         (6 encoded bytes)
"party_a"       (8 encoded bytes)
"party_b"       (8 encoded bytes)
"pact_version"  (13 encoded bytes)

PactTerm (rhes o'r arae terms):

"key"    (4 encoded bytes)
"value"  (6 encoded bytes)

PartyIdentifier (map party_a / party_b):

"label"    (6 encoded bytes)
"contact"  (8 encoded bytes)  ← only if present

3.3 Cyfeirnod Amgodio Byte

Math Amgodiad CBOR Enghraifft
Hash SHA3-256 (32 byte) 0x58 0x20 + 32 byte body_hash, qub_id
Amserlinau (i64) Math mawr 0 (positif) neu 1 (negatif), amgodiad byrraf Eiliadau Unix
Fersiwn (u8, gwerth 1) 0x01 (un byte)
Math cynnwys (u8, gwerth 1) 0x01 (un byte)
sig_alg (u8, gwerth 0) 0x00 (un byte)
Llofnod ML-DSA-65 (3,309 byte) 0x59 0x0C 0xED + 3,309 byte author_signature, cosigner_signature
Allwedd gyhoeddus ML-DSA-65 (1,952 byte) 0x59 0x07 0xA0 + 1,952 byte author_pubkey, cosigner_pubkey

4. Deilliadau Normadol

4.1 qub_id

Mae'r qub_id yn adnabod qub yn unigryw ac yn rhwymo'r QubEnvelope i'r SealedQub. Mae'n cael ei ddeillio'n benderfynol o gynnwys yr amlen.

qub_id = SHA3-256(
    "QUB_ID_V2"    ||    // domain separator: ASCII bytes [0x51 0x55 0x42 0x5F 0x49 0x44 0x5F 0x56 0x32] (9 bytes) + 0x00 padding (1 byte) = 10 bytes
    version        ||    // u8 (1 byte)
    content_type   ||    // u8 (1 byte)
    created_at     ||    // i64 big-endian (8 bytes)
    unlock_at      ||    // i64 big-endian (8 bytes)
    outcome_at_or_zero || // i64 big-endian (8 bytes; 0 when outcome_at is absent)
    drand_round    ||    // u64 big-endian (8 bytes)
    body_hash      ||    // [u8; 32] (32 bytes)
    title_hash           // [u8; 32] (32 bytes; absent-sentinel = [0u8; 32])
)
// Total preimage: 108 bytes → 32-byte output

Amgodio gwahanydd parth: Mae'r llinyn "QUB_ID_V2" yn 9 byte ASCII. Caiff un byte padin 0x00 ei atodi i gyrraedd 10 byte ar gyfer aliniad. RHAID i weithrediadau ddefnyddio'r 10 byte union hyn: [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00].

Amgodio outcome_at: Estynnodd V1.1 y preimage o 92 i 100 byte er mwyn plygu'r maes outcome_at dewisol i mewn i'r rhwymo. Caiff outcome_at absennol ei amgodio fel 8 byte sero; mae dilyswyr y protocol yn gwrthod outcome_at <= 0 ym mhob man fel na all yr arwydd hwn wrthdaro â gwerth dilys. Gweler §3.2 (fformat gwifren) a'r tasks/verdict-uplift-plan.md yn-y-goeden am y mecanwaith dyfarniad sy'n cymell y maes hwn.

Amgodio drand_round: Estynnodd V1.2 y preimage o 100 i 108 byte er mwyn plygu drand_round (y rownd drand darged, §4.3) i mewn i'r rhwymo, a chododd y gwahanydd parth i QUB_ID_V2. Mae hyn yn rhwymo rownd y clo amser i mewn i hunaniaeth y qub: ni all porth ail-rwymo'r cyphertext i rownd wahanol (e.e. un sydd eisoes wedi pasio) na'r hyn y mae'r unlock_at a ddangosir yn ei awgrymu. Mae'r weithdrefn datgloi (§8) hefyd yn dilysu bod y rownd sydd wedi'i phobi i mewn i stanza cyphertext tlock yn cyfateb i unlock_round(unlock_at), felly mae'r amser datgloi a ddangosir yn brofadwy yn rownd sy'n gatio'r datgryptio.

Priodweddau:

4.2 body_hash

body_hash = SHA3-256(body)

Ble mae body yn llwyth tâl cynnwys Vec<u8> amrwd. Ar gyfer qubs testun, dyma yw corff y qub wedi'i amgodio UTF-8.

4.2.1 title_hash

title_hash = SHA3-256(NFC(title).utf8_bytes)   if title is present
title_hash = [0u8; 32]                         if title is absent

Ble mae title yn deitl plaen dewisol a wynebir ar gyfrif i lawr y gwyliwr cyn datgelu (gweler §3.2). Mae normaleiddio NFC yn rhedeg ar amser hash fel bod y crynodeb yn sefydlog ar draws dilyniannau pwyntiau côd sy'n weledol-gyfartal. Mae'r sentinel cyfan-zerod wedi'i gadw ar gyfer yr achos absennol; mae llinyn gwag yn cael ei wrthod ar ffin CBOR safonol fel amgodiad an-safonol o "absennol" (mae'r amgodiad safonol yn hepgor y maes yn gyfan gwbl).

4.3 Mapio Rownd-Datgloi

drand_round = ceil((unlock_at - chain_genesis_time) / chain_period_seconds)
Paramedr Ffynhonnell Enghraifft
unlock_at Eiliadau Unix UTC a ddewiswyd gan y defnyddiwr 1735689600 (2025-01-01 00:00:00 UTC)
chain_genesis_time gwybodaeth cadwyn drand (genesis_time) 1595431050
chain_period_seconds gwybodaeth cadwyn drand (period) 30

Mae'r gweithred ceil() yn dewis y rownd drand gyntaf y mae ei hamser datgelu ≥ unlock_at. Mae hyn yn sicrhau nad yw'r qub yn dod yn datgryptiadwy cyn yr amser datgloi a ddewiswyd.

Achos ymylol: os yw (unlock_at - chain_genesis_time) yn union rannadwy gan chain_period_seconds, y canlyniad yw'r union rownd honno — mae'r qub yn datgloi'n union ar amser datgelu y rownd honno.

Dilysu: RHAID i unlock_at fod yn y dyfodol ar amser selio. RHAID i unlock_at BEIDIO â bod yn fwy na 10 mlynedd o created_at (i gyfyngu risg dibyniaeth drand-hir-orwel; DYLAI'r UI rybuddio ar gyfer dyddiadau datgloi y tu hwnt i 2 flynedd).


5. Newtypes Fformat Gwifren

Mae newtypes fformat gwifren yn darparu diogelwch amser-crynhoi rhag cymysgu bytes CBOR â JSON, testun plaen amrwd, neu amgodiadau byte eraill.

Math Yn Cynnwys Cynhyrchwyd Gan Defnyddir Gan
SealedQubCbor CBOR safonol y SealedQub serialize_sealed_qub() Uwchlwytho storfa parhaol, nôl gwyliwr
QubEnvelopeCbor CBOR safonol y QubEnvelope serialize_qub_envelope() Mewnbwn amgryptio tlock, allbwn datgryptio tlock

5.1 Rheolau Adeiladu

// Production code — only through CBOR serialisers:
let sealed = SealedQubCbor::from_encoded(cbor_bytes);

// There is deliberately NO From<Vec<u8>> implementation.
// You cannot accidentally wrap arbitrary bytes in a wire format type.

// Accessing raw bytes:
let bytes: &[u8] = sealed.as_bytes();
let bytes: Vec<u8> = sealed.into_bytes();

5.2 Dilysu ar Adeiladu

DYLAI from_encoded() ddilysu bod y mewnbwn yn dechrau gyda phennawd map CBOR dilys. Mae dilysu strwythurol llawn yn digwydd ar amser parsio, nid amser adeiladu, er mwyn osgoi parsio-dwbl.


6. Cofrestrfa Math Cynnwys

Gwerth Math Maint Corff Mwyaf Nodiadau
0x00 Wedi'i gadw (annilys) RHAID PEIDIO â'i ddefnyddio
0x01 Testun plaen (UTF-8, Markdown cyfyngedig) 50 KB taledig / 10 KB am ddim Gweler §10 am reolau rendro. Mae'r rhaniad rhad ac am ddim / taledig yn cael ei orfodi gan y gwasanaeth uwchlwytho; mae'r nenfwd caled-haen-protocol yn 50 KB.
0x02 Wedi'i gadw (dyfodol) Wedi'i ddyrannu ar gyfer math cynnwys yn y dyfodol; nid yw'n ddilys yn v1. RHAID i wylwyr ei wrthod fesul y rheol isod.
0x03 Cytundeb (cytundeb dwyochrog, corff CBOR) 100 KB Mae'r corff yn PactTerms CBOR safonol (§6.1). Llofnodi cyd-arwyddwr fesul §9.7.
0x04 Dyfarniad (hunan-raddio gan y crëwr, corff CBOR) 8 KB Mae'r corff yn VerdictBody CBOR safonol (§6.2). Allyrrir gan y bwriad verdict ochr-system yn unig. Mae'r berthynas rhiant ar y tag Arweave Parent-Tx-Id, nid ar y corff. Gweler verdict-uplift-plan §3.4.

RHAID i wylwyr wrthod mathau cynnwys anhysbys gyda gwall clir-weladwy i'r defnyddiwr. RHAID i wylwyr BEIDIO â cheisio rendro mathau anhysbys fel testun.

6.1 Corff Cytundeb (content_type = 0x03)

Mae corff cytundeb yn amgodiad CBOR safonol o werth PactTerms:

PactTerms {
    pact_version:  u8,                    // 0x01 for structured/v1
    title:         String,                // ≤ 200 bytes, NFC
    terms:         Vec<PactTerm>,         // ≤ 20 rows
    party_a:       PartyIdentifier,       // initiator
    party_b:       PartyIdentifier,       // counter-signer
    notes:         Option<String>,        // ≤ 5,000 bytes, NFC; absent key if none
}

PactTerm       { key: String (≤ 100), value: String (≤ 2,000) }   // NFC on both sides
PartyIdentifier{ label: String (≤ 100), contact: Option<String (≤ 320)> }

Rhoddir trefnau allwedd CBOR safonol y tri map yn §3.2. RHAID i gyfanswm CBOR cytundeb wedi'i gyfresoli BEIDIO â mynd y tu hwnt i 100 KB (yn cyfateb â §6).

Gwahaniaethydd sgema. RHAID i'r rhes gyntaf yn terms ar gyfer cytundeb structured/v1 fod yn { key: "pact_schema", value: "structured/v1" }. Mae rhesi heb yr arwydd hwn yn gytundebau "personol" ac nid ydynt yn derbyn dilysu strwythuredig na rendro sgema-ymwybodol.

Tyllau cydnabyddiaeth wedi'u rhewi. Mae cytundebau structured/v1 yn cario'n union bedair rhes cydnabyddiaeth o dan yr allweddi hyn:

"initiator_standard_terms"
"initiator_capacity_terms"
"counterparty_standard_terms"
"counterparty_capacity_terms"

Mae'r value ar gyfer pob un yn un o wyth llinyn Saesneg wedi'u rhewi a ddewiswyd gan y pâr (rôl, math), ble mae rôl ∈ { seller, buyer, provider, client } a math ∈ { standard, capacity }. Mae'r llinynnau eu hunain yn ddata protocol normadol — mae llofnodion ML-DSA-65 y ddau barti yn ymrwymo i'r bytes union trwy body_hash. NID ydynt wedi'u lleoleiddio; mae'r corff wedi'i lofnodi yn iaith-niwtral. Mae unrhyw newid geiriad yn gofyn am fersiwn sgema newydd (structured/v2).

Mae'r wyth llinyn, eu chwilio (acknowledgement_for(role, kind)), a'r rhesymeg ar gyfer pob un wedi'u pinio gan y gweithrediad cyfeirio. RHAID i weithrediadau cydymffurfiol allyrru gwerthoedd cydnabyddiaeth byte-fath; mae profion hash-corff SHA3-256 ffigwr-aur sy'n cwmpasu pob un o'r pedwar cyfuniad rôl yn dal unrhyw ddrifft.

Trefn arddangos y gwyliwr. Mae'r llinynnau cydnabyddiaeth yn cynnwys ymadroddion fel "described above", sy'n rhagdybio bod y rhesi disgrifiad / cwmpas yn rendro o flaen y cydnabyddiaethau. RHAID i wylwyr rendro'r arae terms yn nhrefn CBOR; mae ail-drefnu yn torri semanteg y rhyddiaith.

Cyswllt y gwrthbarti. Pan fydd contact Parti B yn gyfeiriad e-bost dilys, mae'r gwasanaeth uwchlwytho qub yn anfon e-bost gwahoddiad adolygu / cyd-arwyddo yn awtomatig ar amser llwyfannu ac yn rhwymo'r cyd-arwydd terfynol i ddilysu'r un cyfeiriad hwnnw (§9.7). Gellir cyd-arwyddo cytundebau y mae cyswllt Parti B yn absennol ynddynt, ond dim ond trwy sianel allan-o-fand — mae'r gwasanaeth yn gwrthod ceisiadau cyd-arwyddo na allant gynhyrchu marciwr dilysu-e-bost 15-munud cyfatebol.

6.2 Corff Dyfarniad (content_type = 0x04)

Mae corff dyfarniad yn amgodiad CBOR safonol o werth VerdictBody:

VerdictBody {
    verdict_version: u8,                  // 0x01 for structured/v1
    outcome:         u8,                  // 1=Right · 2=Partial · 3=Wrong · 4=Unfalsifiable
    reflection:      Option<String>,      // ≤ 2,000 bytes NFC; "what changed, what did you learn"
    evidence_url:    Option<String>,      // ≤ 2,048 bytes; HTTPS only; absent key when omitted
}

Trefn allwedd CBOR safonol:

"outcome"          (8 encoded bytes)
"reflection"       (11 encoded bytes)  ← only if present
"evidence_url"     (13 encoded bytes)  ← only if present
"verdict_version"  (16 encoded bytes)

RHAID i gyfanswm CBOR dyfarniad wedi'i gyfresoli BEIDIO â mynd y tu hwnt i 8 KB (yn cyfateb â'r rhes gofrestrfa uchod).

Enwm canlyniad. Mae'r byte gwifren yn fwriad-niwtral; mae'r pedwar bwced Right / Partial / Wrong / Unfalsifiable yn cwmpasu gofod canlyniad pob bwriad sy'n dwyn dyfarniad. Mae labeli fesul-bwriad ("Wedi'i alw'n iawn" / "Fe'i cedwais" / "Wedi'i gyflenwi" / "Wedi'i gadarnhau" ar gyfer Right, ac yn y blaen) yn fater rendro ochr-y-gwyliwr a ddatrysir yn erbyn bwriad y qub rhiant — mae'r wifren yn aros yn iaith- a bwriad-niwtral. RHAID gwrthod gwerthoedd y tu allan i 1..=4 wrth ddatgodio.

Cyswllt â'r rhiant. NID yw qub dyfarniad yn cario'r cyfeirnod rhiant yn ei gorff. Allyrrir id trafodiad Arweave y qub rhiant fel y tag storio Parent-Tx-Id ar amser uwchlwytho (haen tag storio §7). Mae hyn yn cadw'r corff yn ddatganiad llofnodedig hunangynhwysol o hunan-asesiad; sefydlir y gadwyn archwilio ("iawn am beth?") trwy'r chwiliad-tag Arweave.

Diogelwch URL tystiolaeth (normadol). Pan fydd evidence_url yn bresennol, RHAID i ddilyswyr (ochr-cyfansoddi, ochr-wifren, ymyl y Worker) orfodi:

  1. HTTPS yn unig. RHAID i'r llinyn ddechrau gyda'r dilyniant beit https://. Caiff unrhyw gynllun arall — http, ftp, javascript, data, file, ac yn y blaen — ei wrthod.
  2. Cap hyd. ≤ 2,048 beit (terfyn URL ymarferol y porwr).
  3. Gwiriad NFC + nodbwynt gelyniaethus. Yr un rheol â title a reflection — gwrthodir nodbwyntiau bidi-override / lled-sero / tag-bloc / BOM / C0 / C1. Mae'r diffiniad yn cyfateb i'r crate::handle::contains_hostile_text_codepoint Rust ac i'r workers/api/src/utils/unicode.ts::isHostileCodepoint TS (cadwch nhw mewn cydgam).
  4. Dim gofod gwyn, dim rheolyddion ASCII. Gwrthodir gofod gwyn / DEL / beitiau is-0x20 unrhyw le yn yr URL — yn cau'r fector chwistrellu \n/\t nad yw'r rheol bidi yn ei orchuddio.
  5. Segment gwesteiwr nad yw'n wag. RHAID i bopeth rhwng https:// a'r /, ?, neu # cyntaf fod yn anwag.

Dim nôl ochr-gweinydd. RHAID i'r Worker BEIDIO â dirprwyo, nôl, na rhagolygu'r URL. Mae'r protocol yn storio llinyn; mae'r rendro'n digwydd ochr-y-gwyliwr gyda rel="nofollow noopener noreferrer" target="_blank" a gwesteiwr gweladwy wedi'i arddangos ochr yn ochr â thestun y ddolen.

Myfyrdod. Testun myfyrdod dewisol wedi'i ysgrifennu gan y crëwr ("beth a newidiodd, beth a ddysgoch"). Yr un dilysu NFC + nodbwynt gelyniaethus â title. Mae mewnbwn gwag / gofod-gwyn yn unig yn cwympo i absennol ar amser adeiladu.

Fersiwn sgema. Mae v1 yn cefnogi verdict_version = 0x01 yn unig. Mae diwygiadau sgema yn y dyfodol yn codi'r beit hwn ac yn glanio ochr yn ochr â fersiwn protocol newydd fesul §12.


7. Protocol Selio

Y dilyniant selio cyflawn. Mae pob cam yn normadol.

 1. User composes plaintext and metadata in ComposeQub.
 2. Validate:
    a. body is non-empty.
    b. body size ≤ max for content_type and user tier (see §6).
    c. unlock_at is in the future.
    d. unlock_at ≤ created_at + 10 years.
    e. content_type is a known, supported value.
 3. Compute body_hash = SHA3-256(body).
 4. Set created_at = current Unix seconds UTC.
 5. Select drand chain. Load chain_genesis_time and chain_period_seconds, and
    compute drand_round = ceil((unlock_at - chain_genesis_time) / chain_period_seconds).
    (Computed here, before qub_id, because drand_round is bound into the qub_id
    preimage — §4.1, V1.2.)
 6. Compute qub_id (see §4.1), folding in drand_round from step 5.
 7. Construct QubEnvelope with all fields.
 8. Serialise QubEnvelope using canonical CBOR → bytes B.
    Assert: serialised output matches canonical profile (§3).
 9. Compute C = tlock_encrypt(B, drand_round, drand_chain_public_key).
10. Construct SealedQub with tlock_ciphertext = C, and matching qub_id, version,
    unlock_at, drand_chain_id, drand_round.
12. Serialise SealedQub using canonical CBOR → SealedQubCbor.
12a. Generate K = 32 random bytes (CSPRNG) and N = 12 random bytes (CSPRNG).
     Compute W = wrap_sealed_qub(SealedQubCbor, qub_id=qub_id, key=K, nonce=N)
     per §13. The bytes uploaded to permanent storage are the OuterWrapper CBOR W,
     never the bare SealedQubCbor. K leaves the device only as the URL
     fragment in step 16.
13. Display seal-time disclosure. User confirms.
14. Validate upload eligibility via the qub upload service (bot-detection, entitlement, rate limits).
15. Submit W (the OuterWrapper bytes) to the qub upload service; the service
    signs and uploads to permanent storage. The service is byte-blind to the inner
    SealedQubCbor and never receives K.
16. Receive arweave_tx_id from the service. Construct delivery URL as
    `<origin>/c/<arweave_tx_id>#<base64url(K)>` (or `<origin>/s/<short_code>#<base64url(K)>`
    when a short code is allocated). Browsers do not transmit URL fragments
    to servers, so K is never observed by qub.social or any storage gateway.

Haen tagiau storfa (allan-o-fand). Mae'r gwasanaeth uwchlwytho qub yn atodi set o dagiau trafodion storfa sydd wedi'u cadw'n fwriadol fach ochr yn ochr â'r llwyth tâl wedi'i amlapio. Mae Content-Type=application/octet-stream yn ofynnol yn normadol. Mae'r gwasanaeth cyfeirio yn atodi tri thag dewisol ychwanegol pan fydd y crëwr yn dewis eu wynebu: Intent (bwriad cyfansoddi wedi'i ddilysu yn erbyn rhestr ganiataol — e.e., quote, reply, commitment), Author (ôl-bys allwedd-gyhoeddus §9.3 y crëwr fel hecs llythrennau bach 64-cymeriad), a Parent-Tx-Id (ID trafodyn storfa y qub rhiant ar gyfer cadwyni ateb, base64url 43-cymeriad).

Mae'r tag Author yn dewis-i-mewn fesul qub: mae ap creu cyfeirio yn ei atodi dim ond pan fydd y defnyddiwr yn galluogi priodoli cyhoeddus yn benodol ar amser selio. Pan fydd y togl i ffwrdd — y rhagosodiad — nid oes tag Author yn cael ei ysgrifennu ac mae'r qub yn anbriodol ar y gadwyn: nid oes dim mewn storfa parhaol yn cysylltu'r uwchlwythiad â handlen, e-bost, na qubs eraill crëwr. Pan fydd y togl ymlaen, mae ôl-bys Author yn datrys i @handle dewisedig y crëwr trwy gadwyn dystiolaeth §9.5. Mae perthnasoedd cadwyn-ateb ac Intent yn an-adnabyddol. Mae'r amlapio allanol (§13) yn amddiffyn corff mewnol rhag cydberthynas cyphertext — gan atal cynaeafwr rhag adnabod a swmp-ddatgryptio uwchlwythiadau ar siâp qub ar ôl i'w rownd drand gyhoeddi.

NID yw'r gwasanaeth cyfeirio yn atodi tagiau App-Name, App-Version, neu Type yn fwriadol: byddai unrhyw hidlydd gwerth-unigol o'r fath yn dychwelyd y corpws qub cyfan i ymholiad GraphQL, sy'n anghyson â chwmpas cyfrinachedd-corff-yn-unig yr amlapio.

RHAID i ddilyswr cydymffurfiol BEIDIO â dibynnu ar unrhyw dag storfa ar gyfer dilysu trydydd-parti §11; mae'r hash corff / qub_id / llofnod yn ymrwymo dim ond i'r CBOR mewnol, byth i'r set tagiau.


8. Protocol Datgloi

Y dilyniant datgloi cyflawn. Mae pob cam yn normadol.

 1. Viewer opens delivery URL. Extract arweave_tx_id from path AND
    K = base64url_decode(fragment) from the URL fragment. If the fragment
    is absent or malformed → display "this URL is missing its decryption
    key" and stop; the viewer MUST NOT contact the storage gateway
    without K, since fetching wrapped bytes the viewer cannot decrypt
    serves no purpose and only leaks the access attempt.
 2. Check denylist. If tx_id is denylisted → display block message. Stop.
 3. Fetch OuterWrapper bytes from permanent storage (with multi-gateway fallback).
 3a. Unwrap: parse the bytes as OuterWrapper (§13), verify the wrapper
    `version` byte is `0x01`, and compute SealedQubCbor =
    unwrap_sealed_qub(OuterWrapper, key=K). Any AEAD authentication
    failure (wrong K, tampered ciphertext, swapped qub_id-as-AAD,
    swapped nonce) → display "this URL's decryption key does not match
    the stored qub" and stop. Authentication failures are
    indistinguishable to the viewer per §13.5.
 4. Parse SealedQubCbor → SealedQub.
 5. Validate: SealedQub.version is known (0x01). Reject unknown versions.
 6. If current time < SealedQub.unlock_at → display countdown. Poll or wait.
 6a. Round-binding check (V1.2). Recompute expected_round =
    ceil((SealedQub.unlock_at - chain_genesis_time) / chain_period_seconds).
    Reject unless SealedQub.drand_round == expected_round AND the round baked
    into the tlock ciphertext stanza (read via the age/tlock header, no signature
    required) == expected_round. The stanza round is the one that actually gates
    decryption; without this check a malicious creator could bind the ciphertext
    to an already-past round while displaying a future countdown, so anyone
    reading the stored bytes could decrypt before unlock_at. Implementations with
    no chain identity (test mocks) skip this check.
 7. Once current time ≥ SealedQub.unlock_at:
    a. Fetch drand round signature for SealedQub.drand_round from drand network.
    b. Compute B = tlock_decrypt(SealedQub.tlock_ciphertext, round_signature).
 8. Parse B → QubEnvelope.
 9. Validate QubEnvelope.version is known.
10. Verify: SHA3-256(QubEnvelope.body) == QubEnvelope.body_hash.
    Fail → integrity error.
11. Verify: QubEnvelope.qub_id == SealedQub.qub_id.
    Fail → integrity error.
12. Verify: QubEnvelope.unlock_at == SealedQub.unlock_at.
    Fail → integrity error.
13. Verify: QubEnvelope.content_type is known and renderable.
    Known values: 0x01 (text), 0x03 (pact). Unknown → display error.
14. If QubEnvelope.sig_alg != 0x00 → verify author signature (see §9.4).
15. If cosigner_pubkey or cosigner_signature present → verify cosigner (see §9.7).
16. Render content using appropriate renderer (see §10 for text, §6 for pact).
17. Construct RevealedQub for display.

9. Llofnodi Awduriaeth

9.1 Rhesymeg

Caiff qubs eu storio mewn storfa parhaol. RHAID i lofnodion awduriaeth aros yn anffugadwy yn ddiderfyn, sef pam mae v1.0 yn defnyddio'r cynllun ôl-gwantwm ML-DSA-65 (FIPS 204) yn hytrach na chynllun clasurol y gallai ei ddiogelwch ddirywio o fewn oes parhaol y qub.

9.2 Cofrestrfa Algorithm

sig_alg Cynllun Maint Allwedd Maint Llofnod
0x00 Dim llofnod (heb ei lofnodi)
0x01 ML-DSA-65 (FIPS 204) 1,952 byte 3,309 byte

RHAID i wylwyr wrthod gwerthoedd sig_alg anhysbys.

9.3 Adeiladu Preimage wedi'i Lofnodi

sig_input = SHA3-256(
    "QUB_AUTHOR_SIG_V1"  ||    // domain separator (17 bytes)
    version              ||    // u8 (1 byte)
    qub_id               ||    // [u8; 32] (32 bytes)
    body_hash            ||    // [u8; 32] (32 bytes)
    unlock_at            ||    // i64 big-endian (8 bytes)
    0x00                       // u8 (1 byte): MUST be 0x00 in v1.0
)

// Total preimage: 91 bytes → 32-byte hash

signature = Sign(author_secret_key, sig_input)

Gwahanydd parth: mae "QUB_AUTHOR_SIG_V1" yn 17 byte ASCII: [0x51, 0x55, 0x42, 0x5F, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x5F, 0x53, 0x49, 0x47, 0x5F, 0x56, 0x31]. Dim padin.

Byte olynol: RHAID i'r 91ed byte preimage fod yn 0x00. Mae'r gweithrediad cyfeirio yn datgelu hyn fel y cysonyn ORG_ID_PRESENT_INDIVIDUAL = 0x00 yn crates/qub-core/src/signing.rs; RHAID i wylwyr sy'n ailadeiladu sig_input ar gyfer dilysu allyrru'r un byte.

Cwmpas llofnod — beth sydd ac nad yw'n cael ei orchuddio. Mae sig_input yn ymrwymo i bedwar maes amlen: version, qub_id, body_hash, unlock_at (yn ogystal â'r gwahanydd parth sefydlog a'r byte org_id_present). Mae tri o'r pedwar yn ddi-ymyriadau strwythurol: mae qub_id ei hun yn deillio o version, content_type, created_at, unlock_at, outcome_at, drand_round, a body_hash trwy preimage §4.1, felly mae unrhyw newid i'r meysydd hynny yn cynhyrchu qub_id gwahanol ac yn annilysu'r llofnod yn drosglwyddadwy. Felly'r wyneb wedi'i ardystio'n uniongyrchol yw:

Maes Wedi'i ardystio gan lofnod Sut
version Mewnbwn uniongyrchol i sig_input
qub_id Mewnbwn uniongyrchol
body_hash Mewnbwn uniongyrchol
unlock_at Mewnbwn uniongyrchol
content_type Yn drosglwyddadwy, trwy preimage qub_id
created_at Yn drosglwyddadwy, trwy preimage qub_id
outcome_at Yn drosglwyddadwy, trwy preimage qub_id
drand_round Yn drosglwyddadwy, trwy preimage qub_id (V1.2)
body Yn drosglwyddadwy, trwy body_hash = SHA3-256(body)
author_pubkey — (ymhlyg) Yr allwedd a ddilysodd y llofnod yw'r awdur, drwy ddiffiniad
sender_label Testun arddangos-yn-unig; cyfnewidiol heb dorri'r llofnod
reply_to Pwyntydd edafu; cyfnewidiol heb dorri'r llofnod
cosigner_pubkey / cosigner_signature Wedi'u llofnodi'n annibynnol dros yr un sig_input (gweler §9.7)
drand_chain_id, tlock_ciphertext, visibility Meysydd allanol SealedQub, nid o fewn yr amlen — wedi'u gorchuddio gan eu di-ymyriadau strwythurol eu hunain (cysondeb rownd / cadwyn) ond nid gan lofnod yr awdur. (Mae drand_round bellach wedi'i rwymo'n drosglwyddadwy trwy preimage qub_id — gweler uchod.)

Goblygiadau diogelwch meysydd heb eu hardystio.

RHAID i weithrediadau sy'n arddangos sender_label neu reply_to i ddefnyddwyr terfynol wynebu'r hunaniaeth wedi'i hardystio (ôl-bys allwedd gyhoeddus, tystiolaeth) fel y prif arwydd hunaniaeth, nid y label.

9.4 Gweithdrefn Dilysu

1. Read sig_alg from QubEnvelope.
2. If sig_alg == 0x00 → unsigned. No verification. Display "unsigned qub."
3. If sig_alg is unknown → reject. Display "unrecognised signature scheme."
4. Extract author_signature and author_pubkey. If either is absent → integrity error.
5. Reconstruct sig_input using fields from QubEnvelope (same formula as §9.3).
6. Verify(author_pubkey, sig_input, author_signature).
7. If verification succeeds → display "signed by [key fingerprint]."
8. If verification fails → display "signature verification failed."

Dilysu llofnod yw'r weithred ddrutaf (yn enwedig ML-DSA-65). DYLAI gael ei berfformio ar ôl i'r holl wiriadau rhatach (hash, qub_id, unlock_at) basio.

9.5 Tystiolaethau Hunaniaeth

Mae tystiolaethau hunaniaeth — mapio'r author_pubkey i honiadau hunaniaeth dynol-adnabyddadwy fel dolen qub, cyfeiriad e-bost, dolen gymdeithasol, neu gymhwyster passkey — yn welliant cynyddol ochr-gwyliwr ac NID yn ofynnol ar gyfer dilysu llofnod. RHAID i wylwyr sy'n datrys tystiolaethau i hunaniaeth arddangos roi'r flaenoriaeth:

handle > email > social > fingerprint

Mae'r ôl-gwymp ôl-bys yn hecs llythrennau bach SHA3-256(author_pubkey); mae bob amser ar gael ar gyfer unrhyw qub wedi'i lofnodi. CAIFF gwylwyr ei dalfyrru ar gyfer ei arddangos — mae'r gwyliwr cyfeirio yn rendro qub: wedi'i ddilyn gan y pedwar byte cyntaf a'r pedwar byte olaf (qub:<8 hex>…<8 hex>).

Gall dilyswr cydymffurfiol gwblhau pob gwiriad yn §9.4 heb gysylltu â'r API qub, heb unrhyw rwydwaith y tu hwnt i storfa parhaol a drand, a heb unrhyw chwilio ochr-gweinydd. Mae datrys tystiolaeth yn gam ymdrech-orau ar wahân a berfformir dim ond ar ôl i ddilysu llofnod lwyddo.

9.6 Effaith Maint

Ed25519 ML-DSA-65
Llofnod 64 byte 3,309 byte
Allwedd gyhoeddus 32 byte 1,952 byte
Cyfanswm fesul qub 96 byte 5,261 byte
Delta cost storfa (ar ~$5/MB) ~$0.0005 ~$0.026

Ar gyfer qub testun o 500–2,000 byte, mae ML-DSA-65 yn treblu'r maint wedi'i storio yn fras. Mae'r gost absoliwt yn ddibwys.

9.7 Dilysu Cyd-arwyddwr (Cytundebau Dwyochrog Cytundeb)

Ar gyfer cytundebau dwyochrog (content_type = 0x03), mae ail haen lofnod yn profi bod y ddau barti wedi cydsynio i'r un telerau.

Meysydd amlen:

RHAID i'r ddau faes fod yn bresennol gyda'i gilydd neu'r ddau yn absennol. Os yw union un yn bresennol, RHAID i wylwyr riportio gwall cywirdeb.

Gweithdrefn dilysu:

1. If cosigner_pubkey absent and cosigner_signature absent → no cosigner. Done.
2. If exactly one is present → integrity error.
3. Verify cosigner_pubkey != author_pubkey (prevent self-cosigning).
   Fail → display "cosigner pubkey must differ from author."
4. Reconstruct sig_input using the same formula as §9.3.
5. Verify(cosigner_pubkey, sig_input, cosigner_signature).
6. Success → display "co-signed by [cosigner fingerprint]."
7. Failure → display "co-signature verification failed."

Priodweddau:

Gât-rhwymo-e-bost (gweithredol). Pan fydd cytundeb wedi'i lwyfannu yn cario cyswllt e-bost Parti B (§6.1), RHAID i'r gwasanaeth uwchlwytho qub wrthod y cais cyd-arwyddo oni bai bod marciwr dilysu-e-bost byrhoedlog yn bodoli sy'n cyfateb i'r ID llwyfannu a hash-e-bost-wedi'i-normaleiddio'r cyswllt hwnnw. Caiff y marciwr ei ysgrifennu gan /api/v1/auth/verify pan fydd y tocyn dolen-hud yn cario staging_id a bod y cyfeiriad wedi'i ddilysu yn cyfateb i SHA-256(normalise_email(party_b.contact)) — ble mae normalise_email(addr) yn cadw cas y rhan leol ac yn lleihau'r rhan parth yn unig (yn unol â RFC 5321 §2.3.11), ac mae SHA-256 yma yn hash NIST FIPS 180-4 (gwahanol i'r SHA3-256 a ddefnyddir mewn deilliadau §4) — ac yn dod i ben 900 eiliad (15 munud) ar ôl cyhoeddi. Mae hyn yn gât gwrth-ddynwarediad gweithredol, NID yn rhan o brawf qub ar-y-gadwyn — mae dilyswr trydydd-parti sy'n ailchwarae §11 angen dim ond storfa parhaol a drand, heb unrhyw chwilio ochr-gweinydd. Mae'r marciwr yn bodoli ar yr ochr gweinydd yn unig ac nid yw byth yn rhan o'r corff wedi'i lofnodi.

Effaith maint (awdur ML-DSA-65 + cyd-arwyddwr):

Cydran Maint
Llofnod awdur 3,309 byte
Allwedd gyhoeddus awdur 1,952 byte
Llofnod cyd-arwyddwr 3,309 byte
Allwedd gyhoeddus cyd-arwyddwr 1,952 byte
Cyfanswm gorbenion crypto 10,522 byte
Delta cost storfa ~$0.05

10. Rendro a Glanhau Markdown

Mae'r adran hon yn ddiogelwch-feirniadol. Mae'r gwyliwr yn rendro qubs testun (content_type = 0x01) gan ddefnyddio is-set Markdown cyfyngedig.

10.1 Elfennau a Ganiateir

10.2 Elfennau Gwaharddedig

Elfen Trin
HTML amrwd (<div>, <script>, ac ati) Wedi'i ddileu'n gyfan gwbl. Nid oes HTML yn pasio drwodd.
Delweddau (![alt](url)) Wedi'u dileu. Mae cystrawen delweddau yn cael ei dynnu o'r allbwn.
Dolenni ([text](url)) URL wedi'i rendro fel testun plaen gweladwy. Heb ei auto-gysylltu. Heb fod yn glic-adwy heb gamau defnyddiwr penodol.
Cynlluniau URL peryglus javascript:, data:, vbscript:, file: — wedi'u dileu.
Iframes, embeds, gwrthrychau Wedi'u dileu.
Endidau HTML Wedi'u datgodio i nodau arddangos dim ond os yw'n ddiogel.

10.3 Gweithrediad

RHAID i weithrediadau ddefnyddio parseu rhestr ganiataol llym, nid rhestr-bloc. Y dull a argymhellir:

  1. Parsio Markdown gan ddefnyddio pulldown-cmark (neu gyfwerth).
  2. Cerdded yr AST a gollwng unrhyw nod nad yw yn y rhestr ganiataol (§10.1).
  3. Ar gyfer nodau dolen: allyrru'r URL fel testun gweladwy, nid fel elfen <a> y gellir ei chlicio.
  4. Trosi'r AST wedi'i hidlo i gynrychioliad canol-gam wedi'i deipio (e.e., enum MarkdownNode gydag amrywiadau diogel yn unig). Mae HTML amrwd yn strwythurol an-gynrychioliadwy yn y IR hwn.
  5. Rendro o'r IR wedi'i deipio i'r haen olwg targed (e.e., cydrannau golwg adweithiol, nodau DOM). Dim cydgysylltiad llinyn HTML na innerHTML ar unrhyw bwynt.

Mae dulliau rhestr-bloc yn fregus oherwydd gall estyniadau Markdown newydd neu cwirciau parser gyflwyno elfennau heb eu hidlo. Mae'r dull AST-wedi'i-deipio yn gwneud XSS yn strwythurol amhosibl — nid oes amrywiad sy'n gallu cario HTML mympwyol.

10.4 Cyfyngiadau Maint a Strwythur


11. Dilysu Trydydd Parti

Gall unrhyw drydydd parti ddilysu qub cyhoeddus heb gydweithrediad qub. Y weithdrefn dilysu:

1. Obtain arweave_tx_id (from delivery URL or direct knowledge).
2. Fetch SealedQubCbor from any storage gateway.
3. Confirm storage block inclusion (block height, block timestamp).
4. Parse SealedQubCbor → SealedQub.
5. Fetch drand round signature for SealedQub.drand_round.
6. tlock_decrypt(tlock_ciphertext, round_signature) → QubEnvelope CBOR bytes.
7. Parse → QubEnvelope.
8. Verify SHA3-256(body) == body_hash.
9. Verify QubEnvelope.qub_id == SealedQub.qub_id.
10. Verify QubEnvelope.unlock_at == SealedQub.unlock_at.
11. If sig_alg != 0x00: verify author_signature (see §9.4).
12. All checks pass → qub is verified.

Beth mae dilysu yn ei brofi:

Prawf Beth y mae'n ei sefydlu
Ymrwymiad Roedd y cyphertext yn bodoli erbyn amserlen bloc y storfa.
Cywirdeb Mae'r corff testun plaen yn cyfateb i'r hash wedi'i ymrwymo ac nid yw wedi cael ei newid.
Amseru Roedd y cynnwys yn anddarllenadwy tan rownd drand, sy'n cyfateb i'r amser datgloi a ddewiswyd (yn amodol ar dybiaethau diogelwch tlock a drand).

Beth NAD yw dilysu yn ei brofi:

An-brawf Pam
Awduriaeth Mae'r sender_label yn addurnol. Heb sig_alg0x01, gallai unrhyw un fod wedi selio'r cynnwys hwn.
Bwriad Mae'r qub yn profi cynnwys ac amseru, nid yr hyn a olygai'r crëwr yn oddrychol.
Amseru cyn-digwyddiad Gall cynhwysiad bloc y storfa fod ar ei hôl hi i uwchlwythiad gwirioneddol o funudau. Amser y bloc yw amserlen yr ymrwymiad, nid yr eiliad y pwysodd y defnyddiwr "selio."

12. Fersiynu

12.1 Fersiwn Protocol

Mae'r maes version (u8) yn SealedQub a QubEnvelope yn adnabod prif fersiwn y protocol.

12.2 Hanes Fersiwn

Fersiwn Gwerth Disgrifiad
v1 0x01 Qubs testun cyhoeddus (content_type 0x01), cytundebau dwyochrog cytundeb (0x03, sgema structured/v1, awdur ML-DSA-65 + cyd-arwyddwr), tlock, SHA3-256

12.3 Cydnawsedd Ymlaen

DYLAI gwyliwr v1 sy'n dod ar draws QubEnvelope gydag allweddi map CBOR dewisol anhysbys (allweddi nad ydynt yn y drefn safonol §3.2) anwybyddu'r allweddi hynny a pharhau â dilysu gan ddefnyddio meysydd hysbys. Mae hyn yn caniatáu ychwanegiadau bach yn y dyfodol (e.e., metadata newydd) heb angen cynnydd prif fersiwn.

DYLAI gwyliwr v1 sy'n dod ar draws sig_alg = 0x01 (ML-DSA-65) ond heb gefnogaeth dilysu ML-DSA-65 arddangos cynnwys y qub gyda hysbysiad "llofnod yn bresennol ond nid yn ddilysadwy", nid gwrthod y qub yn gyfan gwbl. Mae'r gweithrediad cyfeirio heddiw yn gwrthod pob gwerth sig_alg heblaw 0x00 ac 0x01 oherwydd nad oes algorithm dilys arall yn y gofrestrfa v1 — mae gwrthodiad llym a meddal-fethu yn arsylladwy-fath nes bod trydydd algorithm yn cael ei gofrestru. Mae'r ymddygiad meddal-fethu uchod yn dod yn lwyth-eredig unwaith y mae §9.2 yn derbyn cofnod newydd, ac fe ddiweddarir y gwyliwr cyfeirio i feddal-fethu ar y pwynt hwnnw.

12.4 Fersiwn Amlapio Allanol

Mae'r OuterWrapper a ddisgrifir yn §13 yn cario ei byte version ei hun, annibynnol ar SealedQub.version a QubEnvelope.version. Mae'r ddau ofod fersiwn yn esblygu ar wahân: mae amnewid cymesur diogel-ôl-gwantwm yn y dyfodol yn codi'r byte amlapio heb gyffwrdd â fersiwn y protocol mewnol, ac mae ychwanegiad haen-protocol yn y dyfodol (e.e., maes amlen newydd) yn codi'r fersiwn fewnol heb gyffwrdd â'r byte amlapio.

OUTER_WRAPPER_VERSION_* Gwerth Algorithm Statws
OUTER_WRAPPER_VERSION_1 0x01 AES-256-GCM gyda nonce 12-byte, tag dilysu 16-byte, AAD wedi'i rwymo i qub_id rhagosodiad v1
0x020xFF Wedi'u cadw Dyfodol

RHAID i wylwyr wrthod fersiynau amlapio anhysbys gyda gwall clir. Mae'r protocol yn cadw'r gofod fersiwn amlapio yn fwriadol gul nes bod gyrrwr ymfudo concrid yn ymddangos (e.e., arweiniad NIST yn ffafrio AEAD gwahanol); dyrannir slot 0x02 yn yr un diwygiad sy'n cyflwyno'r algorithm.


13. Amlapio Amgryptio Allanol

13.1 Rhesymeg

Mae haenau'r protocol (QubEnvelope → tlock → SealedQub) yn gwneud qub wedi'i selio yn wedi'i gloi-amser: mae'r corff yn anddarllenadwy tan unlock_at ac mae llofnod rownd drand wedi'i gyhoeddi. Ar ôl datgloi, fodd bynnag, mae llofnod y rownd yn gyhoeddus ac mae siâp CBOR safonol SealedQub yn adnabyddadwy, felly gallai cynaeafwr a fynegeiodd drafodion storfa parhaol swmp-ddatgryptio'r corpws qub cyfan.

Mae'r amlapio amgryptio allanol yn cau'r sianel honno trwy interposio haen AEAD gymesur ychwanegol rhwng yr SealedQubCbor safonol a'r bytes wedi'u hysgrifennu i storfa parhaol. Mae'r allwedd 256-bit K yn byw dim ond yn ffragment URL y ddolen drosglwyddo ac ar ddyfeisiau defnyddwyr; nid yw porwyr yn trosglwyddo ffragmentau URL i weinyddion, felly mae qub.social, pob porth storfa, a phob CDN o flaen y naill na'r llall yn arsylladwy-ddall i K. Mae pob qub mewn storfa parhaol felly'n cyphertext ansafonol y mae ei destun plaen yn anadferadwy heb yr URL a ddewisodd y crëwr ei rannu.

Effaith net:

13.2 Haenu

plaintext body                       ← QubEnvelope.body (§2.2)
  ↓ canonical CBOR (§3)
envelope CBOR
  ↓ tlock encrypt to drand round (§7 step 10)
tlock_ciphertext (inside SealedQub) (§2.3)
  ↓ canonical CBOR (§3)
SealedQubCbor bytes                  ← inner wire artifact
  ↓ AES-256-GCM(K, nonce, AAD=qub_id) (§7 step 12a, this section)
OuterWrapper CBOR bytes              ← uploaded to permanent storage (§7 step 15)

Mae selio a datgloi yn yr haen protocol (§7, §8) yn ddigyfnewid o dan ffin yr amlapio; mae'r amlapio yn ymgysylltu ar safle galwad seal() ac yn datgysylltu ar safle galwad unlock().

13.3 Strwythur Data OuterWrapper

struct OuterWrapper {
    version:    u8,           // 0x01, see §12.4
    qub_id:     [u8; 32],     // copied from inner SealedQub; AEAD AAD
    nonce:      [u8; 12],     // 96-bit AEAD nonce
    ciphertext: Vec<u8>,      // AES-256-GCM(K, nonce, SealedQubCbor, AAD=qub_id) || 16-byte tag
}

Diymyriadau maes.

Amgodio CBOR. CBOR safonol fesul §3, gyda'r un rheol trefnu-allweddi (wedi'i drefnu yn ôl hyd byte amgodedig yn esgynnol, yna'n lecsicograffig). Y pedair allwedd yw:

Allwedd Bytes amgodedig Trefn
nonce 6 1
qub_id 7 2
version 8 3
ciphertext 11 4

Mae byte cyntaf CBOR y OuterWrapper felly'n bennawd map o hyd pendant ar gyfer map 4-cofnod (0xA4).

13.4 Rhwymo AAD i qub_id

Mae'r amlapio yn rhwymo qub_id fel data ardystiedig ychwanegol AEAD. Dyma'r amddiffyn strwythurol llwyth-eredig yn erbyn tair dosbarth o ymosodiad:

Ymosodiad Amddiffyn
Symud cyphertext o dan faes qub_id gwahanol yn yr amlapio Annhebygrwydd AAD → mae dilysu AEAD yn methu
Cymysgu ffragment URL qub A gyda bytes storfa parhaol qub B Annhebygrwydd AAD → mae dilysu AEAD yn methu
Ymyrryd â maes qub_id yr amlapio ar ôl uwchlwytho Annhebygrwydd AAD → mae dilysu AEAD yn methu

Nid yw cario qub_id yn nhestun plaen yr amlapio yn gwanhau imiwnedd rhifo'n ystyrlon — mae qub_id ei hun yn hash SHA3-256 o preimage §4.1 heb preimage adferadwy o'r crynodeb, ac mae rhifwr a gynaeafodd y bytes amlapio yn barod yn dysgu dim o'r qub_id gweladwy na allent fynd amdano o fodolaeth yr uwchlwythiad ei hun.

13.5 Algorithmau Amlapio a Dadamlapio

wrap_sealed_qub(SealedQubCbor S, qub_id Q, key K, nonce N):
    require K.len() == 32 and N.len() == 12 and Q.len() == 32
    C := AES_256_GCM_encrypt(key=K, nonce=N, msg=S, aad=Q)
    // C includes the 16-byte authentication tag at the end
    return canonical_cbor_encode(OuterWrapper{
        version:    0x01,
        qub_id:     Q,
        nonce:      N,
        ciphertext: C,
    })

unwrap_sealed_qub(OuterWrapper bytes W, key K):
    require K.len() == 32
    O := canonical_cbor_decode(W) as OuterWrapper
    require O.version == 0x01           // §12.4
    P := AES_256_GCM_decrypt(
            key=K, nonce=O.nonce, ciphertext=O.ciphertext, aad=O.qub_id
         )
    // any AEAD failure → DECRYPT_FAILED, indistinguishable to caller
    return P                            // P is the inner SealedQubCbor

Cwymp modd-methiant. Mae K anghywir, nonce anghywir, annhebygrwydd AAD, a cyphertext sydd wedi'i ymyrryd â hi, i gyd yn cynhyrchu'r un gwall DECRYPT_FAILED. Priodwedd AEAD bwriadol yw hwn: byddai gwahaniaethu'r modd methiant yn creu sianel ochr y gallai ymosodwr o bell ei brofio trwy anfon amlapiadau anffurfiol ac amseru'r ymateb. RHAID i weithrediadau cyfeirio gwympo pob methiant AEAD i un siâp gwall.

13.6 Deunydd Allwedd a Dosbarthu

Mae'r allwedd amlapio K yn werth hap-unffurf 256-bit a gynhyrchwyd fesul-qub gan CSPRNG. Mae'r gweithrediadau cyfeirio yn ei ffynonellu o:

Dosbarthu: RHAID amgodio K fel base64 diogel-URL (RFC 4648 §5, dim padin) a'i atodi i'r ddolen drosglwyddo fel y cydran ffragment:

delivery_url = <origin>/c/<arweave_tx_id>#<base64url(K)>

Nid yw'r ffragment byth yn cael ei drosglwyddo i unrhyw weinydd gan borwr cydymffurfiol. Mae sianeli adfer (mynegai hanes ochr-gweinydd, anfon-awtomatig e-bost dewis-i-mewn) sy'n cadw'r ddolen drosglwyddo lawn — gan gynnwys y ffragment — y tu hwnt i ddyfais y defnyddiwr yn fasnach benodol yn erbyn yr ystum crypto-malu rhagosodedig a RHAID iddynt gael eu gatio ar gydsyniad defnyddiwr penodol.

Colled ffragment. Os bydd defnyddiwr yn colli ffragment yr URL ac nad oes ganddo unrhyw sianel adfer, mae'r qub yn anddarllenadwy. Hwn yw'r fasnach llwyth-eredig yn y dyluniad a RHAID iddo gael ei ddatgelu i'r defnyddiwr ar amser selio. Mae'r MVP yn cryfhau'r datgeliad amser-selio gyda chopi "cadwch yr URL hwn" penodol a sianel adfer e-bost-wedi'i-ddilysu i ddefnyddwyr sy'n dewis i mewn.

13.7 Allan-o-Gwmpas ar gyfer yr Adran Hon

13.8 Qubs cyhoeddus (hepgor amlapio)

Mae'r amlapio allanol yn ddewisol ar yr haen drosglwyddo. Gall crëwr selio qub fel un cyhoeddus, ac yn yr achos hwnnw caiff yr SealedQubCbor safonol ei ysgrifennu i storfa parhaol yn uniongyrchol, heb unrhyw haen OuterWrapper a heb unrhyw allwedd K:

SealedQubCbor bytes  ──(public)──▶  uploaded to permanent storage as-is
SealedQubCbor bytes  ──(private)─▶  AES-256-GCM(K, …) ▶ OuterWrapper ▶ uploaded

Mae qub cyhoeddus wedi'i gloi-amser ond heb ei gatio gan ddolen: mae'n aros yn anddarllenadwy tan i'w rownd drand gyhoeddi (mae'r haen tlock yn ddigyfnewid), ond ar ôl datgloi gall unrhyw un sydd â'r arweave_tx_id ei ddatgryptio — nid oes angen ffragment URL, oherwydd nad oes K. Hon yw'r fasnach fwriadol ar gyfer arwynebau y mae'n rhaid i'r gweinydd eu gyrru: mae e-byst hysbysu-datgelu, embeds trydydd-parti, a SEO cyfoethocach ar ôl datgelu i gyd angen dolen sy'n gweithio heb gyfrinach nad yw'r gweinydd byth yn ei dal (§13.6).

Canlyniadau y mae'n RHAID i gynhyrchydd eu hystyried:

Mae preifat (wedi'i amlapio) yn aros yn rhagosodiad; mae cyhoeddus yn ddewis crëwr penodol fesul-qub.


14. Fectorau Prawf

14.1 Deilliad qub_id

Input:
  version      = 0x01
  content_type = 0x01
  created_at   = 1735689600 (2025-01-01 00:00:00 UTC)
  unlock_at    = 1736294400 (2025-01-08 00:00:00 UTC)
  outcome_at   = absent
  drand_round  = 4695445  (= (1736294400 - 1595431050) / 30, drand mainnet params §14.2)
  body         = "Hello, future."  (UTF-8, 14 bytes)
  title        = absent

Intermediate:
  body_hash  = SHA3-256("Hello, future.")
             = 76ab8b3f843c6ed4f2d0fd75b9f457b4
               ad49dd4450f9c22723ae430e3af3211d
  title_hash = [0u8; 32]   (title absent — §4.2.1 sentinel)

Domain separator (10 bytes):
  [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00]

Preimage (108 bytes — V1.2):
  domain_separator   ||  // 10 bytes
  0x01               ||  // version
  0x01               ||  // content_type
  0x0000000067748580 ||  // created_at as i64 big-endian (1735689600)
  0x00000000677DC000 ||  // unlock_at as i64 big-endian (1736294400)
  0x0000000000000000 ||  // outcome_at_or_zero (outcome_at absent)
  0x000000000047A595 ||  // drand_round as u64 big-endian (4695445)
  body_hash          ||  // 32 bytes
  title_hash             // 32 bytes (all-zeros sentinel; title absent)

Expected output:
  qub_id = SHA3-256(preimage)
         = 3a9fcb31b750d985c262fada6d4f777f
           d6a28be831d941d85c131f5a4bbaf8a4

RHAID i weithrediadau gynhyrchu gwerthoedd body_hash a qub_id union yr un fath ar gyfer y mewnbwn hwn. DYLAI'r fector prawf hwn fod y prawf uned cyntaf a ysgrifennir. Cyfrifwyd y gwerthoedd safonol uchod gan y gweithrediad cyfeirio a RHAID iddynt gyfateb bit-am-bit. Cynlluniau preimage hanesyddol (cyn-lansio — nid oedd unrhyw qubs byw yn dibynnu arnynt): y qub_id V1.0 92-byte oedd 3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0; y qub_id V1.1 100-byte (ar ôl plygu outcome_at_or_zero i mewn) oedd b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed. Mae V1.2 yn plygu drand_round i mewn ac yn codi'r gwahanydd parth i QUB_ID_V2.

14.2 Mapio Rownd-Datgloi

Input:
  unlock_at           = 1735689600
  chain_genesis_time  = 1595431050
  chain_period_seconds = 30

Calculation:
  (1735689600 - 1595431050) / 30 = 4675285.0
  ceil(4675285.0) = 4675285

drand_round = 4675285

14.3 Tro Cylch CBOR Safonol

RHAID i weithrediadau ddilysu bod serialize(parse(serialize(qub))) == serialize(qub) ar gyfer pob mewnbwn dilys. Mae hwn yn brawf priodwedd, nid yn fector sengl.

14.4 CBOR PactTerms (content_type 0x03)

Input:
  pact_version = 1
  title        = "Scooter deposit"
  terms        = [
    { key: "Item",    value: "Honda Metropolitan scooter" },
    { key: "Price",   value: "$100" },
    { key: "Deposit", value: "$10" }
  ]
  party_a      = { label: "Alice" }
  party_b      = { label: "Bob", contact: "bob@example.com" }
  notes        = absent

Canonical CBOR key order (PactTerms):
  "notes"(6) < "terms"(6) < "title"(6) < "party_a"(8) < "party_b"(8) < "pact_version"(13)

Canonical CBOR key order (PactTerm):
  "key"(4) < "value"(6)

Canonical CBOR key order (PartyIdentifier):
  "label"(6) < "contact"(8)

Cyfrifir y bytes CBOR safonol a'r body_hash SHA3-256 gan y gweithrediad cyfeirio. RHAID i weithrediadau gynhyrchu CBOR byte-fath ar gyfer y mewnbwn hwn.

RHAID i weithrediadau hefyd ddilysu bod serialize(parse(serialize(pact))) == serialize(pact) ar gyfer pob mewnbwn PactTerms dilys (prawf priodwedd).

14.5 Fectorau Traws-Iaith Amlapio Allanol

Mae gan yr amlapio allanol (§13) ffigwr safonol ar wahân ar crates/qub-core/tests/vectors/wrapper_v1.json. Mae pob achos yn sefydlogi tupl (key, nonce, qub_id, sealed_cbor) fel mewnbynnau hecs di-ddehongli ac yn haeru allbwn expected_wrapper_hex penodol. Mae'r ddau weithrediad cyfeirio'n defnyddio'r un ffeil JSON:

Mae'r ffigwr ar hyn o bryd yn pinio tri achos:

Achos Cwmpas
basic-text-public Y siâp SealedQub realistig lleiaf; dim meysydd dewisol. Yn sefydlu siâp amlapio safonol ar gyfer qub typig v1.0.
with-recipient-pubkey SealedQub gyda recipient_pubkey wedi'i osod (llwybr Cam 2). Set allwedd CBOR mewnol gwahanol, qub_id gwahanol.
longer-body Corff ~4 KiB — yn ymarfer ragddodiaid hyd CBOR aml-byte y tu mewn i'r amlen mewnol a'r cyphertext allanol.

RHAID i weithrediadau gynhyrchu expected_wrapper_hex byte-fath ar gyfer y mewnbynnau a recordiwyd. Mae adfywio'r ffigwr yn gofyn QUB_REGEN_VECTORS=1 cargo test -p qub-core --test wrapper_vectors ac mae wedi'i gadw ar gyfer newidiadau fformat bwriadol.


15. Llywodraethu Proffil Crypto (Dyfodol)

Mae'r adran hon yn wybodaethol ar gyfer v1 ac yn dod yn normadol y tro cyntaf y mae ail algorithm yn dod i mewn i unrhyw un o primitifau cryptograffig qub.

15.1 Ystum Cyfredol

Mae protocol v1 yn rhwymo'n union un algorithm fesul primitif:

Mae dilyswyr ar hyn o bryd yn caled-godio hydoedd allwedd a llofnod fesul primitif. Nid oes unrhyw wyneb hyblygrwydd yn cael ei amlygu gan y fformat gwifren.

15.2 Siâp Bwriadedig

Pan fydd ail algorithm yn dod i mewn i'r protocol, caiff y dilyswr ei gyflunio ar gyfer CryptoProfile enwedig (e.e., ExqubV1) sy'n rhestru'r set union o werthoedd a ganiateir fesul primitif — sig_algs, cadwyni drand, fersiynau amlapio, mathau cynnwys. Mae'r proffil yn sefydlog ar amser dilysu, byth wedi'i negodi yn-band. Mae unrhyw werth y tu allan i'r proffil gweithredol yn cael ei wrthod.

Mae hyn yn gwarantu na all ychwanegu ML-DSA-87 nac actifadu Ed25519 wanhau cyfluniadau dilysu sy'n bodoli yn ôl-weithredol: mae dilyswr v1 yn aros yn ddilyswr v1 hyd yn oed ar ôl i broffil v2 gael ei gyhoeddi.

15.3 Amodau Sbarduno

Hyrwyddwch §15 i statws normadol pan gynigir unrhyw un o'r canlynol:

Hyd hynny mae §15 yn ddalwr lle sy'n sefydlogi siâp yr ymfudo fel bod PRs y dyfodol yn glanio yn erbyn targed hysbys yn hytrach nag ail-ddadlau'r wyneb negodi o'r dechrau.