← The board

C10 Integration keys

Area
C — Trust & correctness
Audience
operator
Kind
feature
Status
accepted
Maturity
built
Labels
security, web
Relates to
C6D10F12F13G1B5N29

The feature in the specification · Read at

Requirements

  1. C10-R1acceptedMUST

    An operator MUST be able to mint a named key with exactly one scope, read, act or member:<account>, at the command line and over the web API.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    recorded done
    sdk-tssrc/client.tssrc/keys.test.ts::are minted with the password in the body, and the secret comes back once
    cited by
    lemonfiber@a20047c4c3lemonfiber-web@024caedc17lemonfiber-web@b4db1690e0sdk-ts@34b4705686
  2. C10-R2acceptedMUST

    Over the web API, only an operator session MUST be able to mint or revoke a key, except as C10-R15 allows a member, and minting MUST require the operator's proof in the same request: the operator password, or a signature from a registered device key over a challenge the core issued for that request (C10-R24, C10-R25). A key MUST NOT be able to mint, list or revoke keys, whatever its scope.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3lemonfiber-web@024caedc17
  3. C10-R3acceptedMUST

    A key's secret MUST appear only in the reply that minted it or, for a key minted as a claim, only in the reply that collected it (C10-R20), sent with Cache-Control: no-store, and MUST be stored only as a digest. No read, listing, log, support bundle, alert or journal entry MUST carry it.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@41fdc1b377lemonfiber@a20047c4c3lemonfiber-web@024caedc17lemonfiber-companion@da105d58a3sdk-python@dffcdc092a
  4. C10-R4acceptedMUST

    The mint reply MUST carry the stack's certificate pin beside the secret, and the stack's address where it has been served encrypted on the network. Where it has not, the reply MUST carry no address and MUST say how to serve the stack so another machine can connect.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3
  5. C10-R5acceptedMUST

    A key MUST survive a restart and MUST travel in X-Lemonfiber-Token. A revoked, orphaned or unknown key MUST be refused exactly as a wrong token is, with the same status, sentence and code, from its next request.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3sdk-python@99ec2357d0
  6. C10-R6acceptedMUST

    Keys MUST be listed by name, scope, state, minting time and last use, without their secrets, and MUST be revocable by name, at the command line and over the web API.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    recorded done
    sdk-tssrc/client.tssrc/keys.test.ts::are listed from the keys route, with the token as a headersrc/keys.test.ts::are revoked by name, sent as one path segment
    cited by
    lemonfiber@a20047c4c3lemonfiber-web@024caedc17sdk-ts@34b4705686sdk-php@8af096c45bsdk-php@81053d360e
  7. C10-R7acceptedMUST

    A read key MUST be admitted to every served read and the event stream and to no action.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3
  8. C10-R8acceptedMUST

    An act key MUST be admitted to what read admits and to exactly the actions the contract publishes as callable by a key. Any other action MUST be refused, naming the key's scope.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3sdk-ts@bb38134654sdk-php@192d7f4324sdk-python@1c593f02d6
  9. C10-R9acceptedMUST

    The actions callable by a key MUST be published in the contract, each saying whether it disturbs the running system and whether it can be rehearsed. Uninstalling, any action on a credential, a key or the password, installing, updating or removing a plugin, a reset and a restore MUST NOT be callable by a key.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3sdk-ts@bb38134654sdk-php@192d7f4324sdk-python@1c593f02d6
  10. C10-R10acceptedMUST

    A member:<account> key MUST be admitted to exactly what that account's own session admits, and MUST be refused once the account leaves the household.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3
  11. C10-R11acceptedMUST

    A key MUST NOT be accepted from another machine except over the TLS its pin verifies. A key presented from another machine without it, or over a connection whose origin cannot be placed, MUST be refused before it is checked, with a refusal code of its own.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3
  12. C10-R12acceptedMUST

    Every mint and revoke MUST be journaled and MUST raise an operator alert naming the key and its scope. A mint MUST be journaled as reversible, its undo revoking the key, and a revoke MUST be journaled as not reversible.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3
  13. C10-R13acceptedMUST

    A presented value shaped like a key that matches no key MUST count against the same surface-wide limit as wrong passwords, and a revoked or orphaned key MUST NOT. While that limit holds, a request carrying a value shaped like a key MUST be refused with the wait before the value is checked, and a right key MUST NOT reset the count.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3
  14. C10-R14acceptedMUST

    Minting a key under a name another key holds MUST be refused, naming that key.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3
  15. C10-R15acceptedMUST

    A setting, LEMONFIBER_MEMBER_KEYS, off by default and changeable only by the operator, MUST decide whether household members may mint keys. While it is on, a member session MUST be able to mint a member: key scoped to that member alone, giving their own password again in the same request, checked by the media server and counted against the same limits as their sign-in, and MUST NOT be able to mint any other scope or a key for another account. While it is off, a member's mint MUST be refused with a refusal code of its own, and a member MUST still be able to revoke the keys scoped to them.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-api/src/admission/proving.rscrates/lemonfiber-core/src/keys/run.rs
    cited by
    lemonfiber@8bb22330ca
  16. C10-R16acceptedMUST

    A member-minted key MUST be listed to the operator, marked as member-minted, and MUST be revocable by the operator as well as by the member. Its mint and revoke MUST be journaled and MUST alert the operator (C10-R12). A member's listing MUST show only the keys scoped to them, and a key that is not theirs MUST be answered to them as a key that does not exist.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-api/src/admission/proving.rscrates/lemonfiber-core/src/keys/run.rs
    cited by
    lemonfiber@8bb22330ca
  17. C10-R17acceptedMUST

    Every key MUST carry a purpose chosen when it is minted, home-assistant, mcp or other, shown in the listing as the minter's declaration rather than as anything the core verified.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/admission.rscrates/lemonfiber-api/src/entitled.rs
    cited by
    lemonfiber@a20047c4c3lemonfiber-web@024caedc17
  18. C10-R18acceptedMUST

    A key MUST be able to be minted as a claim, at the command line and over the web API. Its reply MUST carry no secret but a key link, lemonfiber://key? followed by these parameters, percent-encoded and no others: address, fingerprint, stack, expires and claim. The listing MUST show the key as waiting to be collected until it is. Where the reply could carry no address (C10-R4), a claim MUST NOT be minted, and the refusal MUST say how to serve the stack so another machine can connect.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run/claimed.rscrates/lemonfiber-core/src/keys/claiming.rscrates/lemonfiber-core/src/companion.rscrates/lemonfiber/src/render/keys.rscrates/lemonfiber-api/tests/integration/what_a_claim_collects.rs
    recorded partial
    sdk-pythonsrc/lemonfiber/keys.pytests/test_keys.py::test_a_key_minted_as_a_claim_asks_for_one_and_is_answered_with_its_linktests/test_keys.py::test_a_key_link_is_read_as_a_claims_mint_writes_it
    cited by
    lemonfiber@081b2de990lemonfiber@41fdc1b377lemonfiber-web@7187c6e791sdk-ts@3af3f58b30sdk-python@dffcdc092aintegration-home-assistant@2f9050847aintegration-mcp@256c7e49da
  19. C10-R19acceptedMUST

    The core MUST keep a claim only as a hash on the key it was minted for. A claim MUST collect its key once, and only within ten minutes of the mint; collecting, lapsing or the key's revocation MUST end it.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/claiming.rscrates/lemonfiber-core/src/keys.rscrates/lemonfiber-core/src/keys/claiming/tests.rscrates/lemonfiber-core/src/keys/run/claimed/tests.rs
    cited by
    lemonfiber@41fdc1b377
  20. C10-R20acceptedMUST

    A key MUST be collected by a request carrying its claim alone, in the body, over the TLS the link's fingerprint verifies (C10-R11). The reply MUST carry the key's secret, name, scope and the stack's pin, sent with Cache-Control: no-store. An unknown, spent or lapsed claim MUST be refused with one status, sentence and code, and MUST count against the same surface-wide limit as wrong passwords (C10-R13).

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/router.rscrates/lemonfiber-core/src/keys/run/claimed.rscrates/lemonfiber-api/tests/integration/what_a_claim_collects.rs
    recorded partial
    sdk-pythonsrc/lemonfiber/keys.pytests/test_keys.py::test_a_claim_collects_its_key_over_the_tls_its_link_pins_with_no_credentialtests/test_keys.py::test_a_claim_is_sent_nowhere_but_the_certificate_its_link_pins
    cited by
    lemonfiber@41fdc1b377lemonfiber-web@7187c6e791sdk-python@dffcdc092aintegration-home-assistant@2f9050847aintegration-mcp@256c7e49da
  21. C10-R21acceptedMUST

    Collecting a key MUST be journaled and MUST raise an operator alert naming the key, its purpose and the address it was collected from. A key whose claim lapses uncollected MUST be revoked, journaled as not reversible, and alerted.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys/run/claimed.rscrates/lemonfiber-core/src/keys/run/heard.rscrates/lemonfiber-core/src/journal.rscrates/lemonfiber-core/src/keys/run/claimed/tests.rs
    cited by
    lemonfiber@41fdc1b377
  22. C10-R22acceptedMUST

    Every surface that shows a key link MUST also draw it as a QR code from the link, and MUST NOT show the link or the code again once that screen is left.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber/src/render/keys.rscrates/lemonfiber-core/src/keys/claiming.rs
    cited by
    lemonfiber@41fdc1b377
  23. C10-R23acceptedMUST

    An operator session MUST be able to register a device key over the web API: a name, the public half of a P-256 key pair and the platform's attestation of where the key lives (an Android key attestation chain, or an iOS App Attest attestation whose client data hash is the SHA-256 of the public half's encoding, hashed once), with the operator password in the same request. The core MUST verify the attestation and record the key's backing as strongbox, enclave or tee, enclave meaning on iOS that App Attest vouched for the genuine app that placed the key there, not that the hardware proved it, and MUST refuse, each with a code of its own, a registration with no attestation, an attestation that does not verify or does not cover the public half, and an attestation placing the key in software. The core MUST keep only the public half and its backing under that name, MUST refuse a name or a public half another device key holds, naming it, and MUST refuse a public half that is not a P-256 key with a code of its own. A member session and a key MUST NOT be able to register, list or revoke device keys. Every registration MUST be journaled and MUST raise an operator alert naming the device key.

    locked by
    0.18.0 met
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/run.rscrates/lemonfiber-core/src/device_keys/attestation.rscrates/lemonfiber-core/src/device_keys/attestation/android.rscrates/lemonfiber-core/src/device_keys/attestation/apple.rscrates/lemonfiber-core/src/device_keys/attestation/chain.rscrates/lemonfiber-core/src/device_keys/public.rscrates/lemonfiber-api/src/device_keys.rscrates/lemonfiber-core/src/device_keys/run/tests.rscrates/lemonfiber-api/tests/integration/what_a_device_key_proves.rs
    cited by
    lemonfiber@34b804b67e
  24. C10-R24acceptedMUSTClaim it

    An operator session MUST be able to ask for a challenge for a registered device key. The core MUST issue a fresh random value of at least 32 bytes, keep it only in memory, bound to that session and that device key, and accept it for one request within one minute; using it, its lapsing, the session ending and the device key's revocation MUST end it.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/challenge.rscrates/lemonfiber-api/src/device_keys.rscrates/lemonfiber-core/src/device_keys/challenge/tests.rscrates/lemonfiber-api/tests/integration/what_a_device_key_proves.rs
  25. C10-R25acceptedMUSTClaim it

    A mint carrying a device key's name, a challenge and a signature in place of the password MUST be admitted only where the device key is registered, the challenge stands for that session and that device key, and the signature verifies against the device key's public half over the challenge and the mint's name, scope, purpose and whether it is a claim, in the form the contract publishes. An unregistered or revoked device key MUST be refused with a code of its own; a challenge that does not stand, for any reason, with one code; and a signature that does not verify with a code of its own, counted against the same surface-wide limit as wrong passwords (C10-R13).

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/proof.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-core/src/device_keys/proof/tests.rscrates/lemonfiber-api/tests/integration/what_a_device_key_proves.rs
  26. C10-R26acceptedMUSTClaim it

    Device keys MUST be listed by name, the fingerprint of their public half, their backing, registration time and last use, and MUST be revocable by name, over the web API, with effect at the next challenge. Every revoke MUST be journaled as not reversible and MUST raise an operator alert naming the device key.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/run.rscrates/lemonfiber-core/src/device_keys/run/heard.rscrates/lemonfiber-api/src/device_keys.rscrates/lemonfiber-core/src/device_keys/run/tests.rscrates/lemonfiber-api/tests/integration/what_a_device_key_proves.rs
  27. C10-R27acceptedMUSTClaim it

    Changing the operator password MUST revoke every device key, journaled and alerted as C10-R26 says.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/run.rscrates/lemonfiber/src/ui.rscrates/lemonfiber-core/src/device_keys/run/tests.rs
  28. C10-R28acceptedMUSTClaim it

    A device key's signature MUST prove the operator for the one mint it was made for and nothing else: it MUST NOT admit a request, stand in for a session or the password anywhere else, or be accepted without an operator session.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-api/src/keys.rscrates/lemonfiber-api/src/device_keys.rscrates/lemonfiber-api/tests/integration/what_a_device_key_proves.rs
  29. C10-R29acceptedMUSTClaim it

    The core MUST register a device key only where its attestation names an app identity the core trusts: the package and the SHA-256 digest of its signing certificate on Android, the Team ID and bundle ID on iOS. The build MUST ship the official NightWorksIO companion's identities, and an attestation naming any other app MUST be refused with a code of its own, naming the identity. Until the companion's first store release the official list MUST be empty, so only the identities the operator adds are trusted, and the core release that follows the companion's first store release MUST ship its identities (releasing).

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/identity.rscrates/lemonfiber-core/src/device_keys/attestation/android.rscrates/lemonfiber-core/src/device_keys/attestation/apple.rscrates/lemonfiber-core/src/device_keys/identity/tests.rs
  30. C10-R30acceptedMUSTClaim it

    The operator MUST be able to add and remove the identities of their own builds as a setting, at the command line and over the web API (ARCH-R262); each change MUST be journaled and MUST raise an operator alert naming the identity, the official identities MUST NOT be removable, and removing an identity MUST revoke every device key registered from it.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/identity.rscrates/lemonfiber-core/src/device_keys/run.rscrates/lemonfiber-core/src/device_keys/run/heard.rscrates/lemonfiber-core/src/settings/changing.rscrates/lemonfiber-core/src/device_keys/run/tests.rs
  31. C10-R31acceptedMUSTClaim it

    The core MUST verify an attestation against the platform roots shipped in its build and MUST NOT send any request to verify one, a revocation list included.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/attestation/chain.rscrates/lemonfiber-core/src/device_keys/attestation/chain/tests.rs
  32. C10-R32acceptedMUSTClaim it

    Restoring a configuration backup MUST revoke every device key once the restore lands, each journaled as not reversible and alerted as C10-R26 says.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/run.rscrates/lemonfiber-core/src/app/restore.rscrates/lemonfiber-core/src/app/restore/tests.rscrates/lemonfiber-core/src/device_keys/run/tests.rs
  33. C10-R33acceptedMUSTClaim it

    A key minted with a device key's signature MUST record that device key, and the listing MUST show it beside the key (ARCH-R293). Revoking a device key MUST NOT revoke the keys it proved, and its alert MUST name each active key it proved.

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/keys.rscrates/lemonfiber-core/src/keys/run.rscrates/lemonfiber-core/src/device_keys/run/heard.rscrates/lemonfiber-api/src/keys.rscrates/lemonfiber-core/src/device_keys/run/tests.rscrates/lemonfiber-api/tests/integration/what_a_device_key_proves.rs
  34. C10-R34acceptedMUSTClaim it

    The core MUST refuse, with a code of its own whose words name no key material, an Android key attestation any certificate of which carries a serial number that the build's snapshot of Google's attestation status list lists as revoked or suspended. Each build MUST embed that snapshot, taken at release time and recording where it was read from and when; the core MUST NOT fetch the list at run time (C10-R31), and MUST report when its snapshot was taken in the version it answers with (ARCH-R294, releasing).

    locked by
    0.18.0 uncited
    recorded done
    lemonfibercrates/lemonfiber-core/src/device_keys/attestation/status.rscrates/lemonfiber-core/src/device_keys/attestation/roots/google-statusscripts/take_the_attestation_status.pycrates/lemonfiber-core/src/device_keys/attestation/android/tests.rscrates/lemonfiber-core/src/device_keys/attestation/status/tests.rs