Requirements
Every capability in the vocabulary MUST have a published, versioned contract generated from the core's port types, and the core MUST reach every service only through a contract it speaks.
The core MUST hold no code specific to any service, and an architecture check MUST refuse a bundled service's name in core code outside the bundle.
A service MUST declare the contracts it speaks, and a manifest MUST NOT name an in-process adapter.
- locked by
- 0.18.0 open
Every answer from an adapter MUST be held to its contract's schema and bounded in size and time, and an answer outside them MUST be refused and MUST NOT be read.
The core MUST reach an adapter only with a key minted for that plugin alone, on a network shared only by the core, the adapter and its upstream, and an adapter MUST NOT be given a credential lemonfiber holds for anything else.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/plugin/placing.rscrates/lemonfiber-core/src/app/plugins/writing.rscrates/lemonfiber-core/src/topology.rscrates/lemonfiber-adapter-kit/src/lib.rscrates/lemonfiber-core/src/app/plugins/tests/writing.rs::an_adapters_key_is_minted_once_kept_after_and_never_made_upcrates/lemonfiber-adapter-kit/src/tests.rs::nothing_is_answered_without_the_plugins_keycrates/lemonfiber-core/src/topology/tests.rs::an_adapter_and_its_upstream_share_a_network_nothing_else_joinscrates/lemonfiber-core/src/plugin/container/tests/model.rs::a_secret_is_read_from_the_store_unless_its_holder_lets_it_cross
- cited by
- lemonfiber@00a691442flemonfiber@d24986d65d
A plugin MUST NOT fill a capability unless its adapter conforms to that capability's contract, proved by recordings against its pinned upstream and by a live conformance pass at install, and first-party adapters MUST be held to the same suite; a first-party plugin the bundle assembles, which has no adapter, MUST fill a capability only through its claims, each proved against its recordings as F9-R2 holds a bundled service's.
Every part of the bundle MUST be a first-party plugin, installed, updated, removed and validated by the path any plugin takes, and the bundle and its first-party manifests MUST be embedded in the binary.
- locked by
- 0.18.0 unmarked
- recorded partial
- lemonfibercrates/lemonfiber-bundle/src/lib.rscrates/lemonfiber-bundle/src/rules.rscrates/lemonfiber-bundle/src/tests.rscrates/lemonfiber-bundled/build.rscrates/lemonfiber-bundled/src/lib.rscrates/lemonfiber-core/src/plugin/first_party.rscrates/lemonfiber-plugin/src/tests.rs
- cited by
- lemonfiber@1b21a54b05
The vocabulary MUST name proxy.front, dashboard.show, quality.sync, archive.extract, stream.guard, invite.decline and request.gate, each with a contract, and every capability in the vocabulary MUST be asked by something in the bundle or by the core over its contract.
- locked by
- 0.18.0 unmarked
- recorded partial
- lemonfibercrates/lemonfiber-contract/src/capabilities/proxy.rscrates/lemonfiber-contract/src/capabilities/quality.rscrates/lemonfiber-contract/src/capabilities/dashboard.rscrates/lemonfiber-contract/src/capabilities/archive.rscrates/lemonfiber-contract/src/capabilities/stream.rscrates/lemonfiber-contract/src/capabilities/invite.rscrates/lemonfiber-contract/src/capabilities/request.rscrates/lemonfiber-ports/src/service/proxying.rscrates/lemonfiber-ports/src/service/syncing.rscrates/lemonfiber-ports/src/service/showing.rscrates/lemonfiber-ports/src/service/extracting.rscrates/lemonfiber-ports/src/service/guarding.rscrates/lemonfiber-ports/src/service/declining.rscrates/lemonfiber-ports/src/service/gating.rscrates/lemonfiber-contract/src/capabilities/tests/proxy.rscrates/lemonfiber-contract/src/capabilities/tests/quality.rscrates/lemonfiber-contract/src/capabilities/tests/dashboard.rscrates/lemonfiber-contract/src/capabilities/tests/archive.rscrates/lemonfiber-contract/src/capabilities/tests/stream.rscrates/lemonfiber-contract/src/capabilities/tests/invite.rscrates/lemonfiber-contract/src/capabilities/tests/request/gate.rscontract/capabilities/index.jsoncrates/lemonfiber-plugin/src/vocabulary/carried/configured.rscontract/capability-vocabulary.jsoncrates/lemonfiber-core/tests/integration/what_the_bundled_stack_provides_and_asks.rscrates/lemonfiber-core/src/app/invite/declining/configured.rscrates/lemonfiber-core/src/app/invite/declining/configured/tests.rscrates/lemonfiber-core/src/app/invite/declining.rscrates/lemonfiber-core/src/seed/run/decline.rscrates/lemonfiber-core/src/seed/run/quality.rscrates/lemonfiber-core/src/seed/run/tests/quality.rscrates/lemonfiber-core/src/app/gating/configured.rscrates/lemonfiber-core/src/seed/run/gate.rs
- cited by
- lemonfiber@13105d3ff2lemonfiber@146bf6191alemonfiber@36bbdb1b09lemonfiber@715e9afd0elemonfiber@7343ad109flemonfiber@6b20b478celemonfiber@e4312fc438lemonfiber-decline@ff03d0dc7elemonfiber-media-stack@dc1463a1f5lemonfiber-media-stack@4a84719402lemonfiber-plugins@116356c0a1
A plugin MAY ask for capabilities and MUST NOT link to a service by name.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-plugin/src/refusing/asking.rscrates/lemonfiber-manifest/src/container/values.rscrates/lemonfiber-core/src/plugin/installed.rscrates/lemonfiber-plugin/src/refusing/asking/tests.rs::a_variable_asking_the_address_of_anything_but_a_core_capability_is_refusedcrates/lemonfiber-plugin/src/refusing/asking/tests.rs::an_ask_carrying_a_service_to_reach_is_refused_by_the_schemacrates/lemonfiber-plugin/src/refusing/asking/tests.rs::an_ask_for_a_namespaced_capability_is_refused_as_naming_a_plugincrates/lemonfiber-manifest/src/container/tests.rs::an_address_names_a_core_capability_and_a_secret_one_declaredcrates/lemonfiber-manifest/src/container/tests.rs::only_the_egress_guard_is_a_network_to_run_inside_and_never_ones_owncrates/lemonfiber-core/src/wiring/tests/asking.rs::a_plugins_ask_follows_the_stacks_and_says_whose_service_asked
- cited by
- lemonfiber@e2005b9828
The stream guard's filler MUST enforce the guard the media server's filler declares, and every location the core gives a member MUST be built from templates the media server's filler declares.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/seed/run/enveloping.rscrates/lemonfiber-ports/src/service/declaring.rscrates/lemonfiber-core/src/seed/run/tests/enveloping.rs::a_guard_speaking_the_contract_is_handed_the_envelope_and_then_holds_itcrates/lemonfiber-ports/src/service/declaring/joined/tests.rs::a_location_is_its_template_on_the_household_address_with_the_item_in_placecrates/lemonfiber-ports/src/service/declaring/tests.rs::a_location_built_anywhere_but_on_the_household_address_is_refused
- cited by
- lemonfiber@00a691442f
Substituting a filler MUST stop the part it replaces and take it out of its form while keeping its data, undoing it MUST bring that part back with its data, and the rehearsal MUST say what does not carry over.
- locked by
- 0.18.0 open
A plugin's service MAY declare shape = "egress-guard" only where it is the upstream an adapter of the same plugin fronts and that adapter speaks network.egress-guard, or where it is the plugin's one service and provides network.egress-guard itself, which lemonfiber MUST honour only where the bundle assembles the plugin and MUST refuse at install and update naming service <id>.shape; any other service declaring it MUST be refused at validation naming service <id>.shape; and lemonfiber MUST write that service's entry as every plugin's entry plus exactly the NET_ADMIN capability and the /dev/net/tun device, and MUST write neither for any other service.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-plugin/src/schema.rscrates/lemonfiber-plugin/src/refusing/shaping.rscrates/lemonfiber-plugin/src/refusing/shaping/tests.rscrates/lemonfiber-core/src/plugin/container.rscrates/lemonfiber-core/src/plugin/container/tests.rscontract/plugin-manifest.schema.jsoncrates/lemonfiber-core/src/app/plugins/tests/updating.rs::an_update_to_a_version_whose_one_service_guards_the_egress_is_refused
- cited by
- lemonfiber@00a691442flemonfiber@5e3ef10f70lemonfiber@0e9fbff3d7lemonfiber-web@88590bbc5d
An adapter MUST declare the upstream releases it supports, each proved by its own recordings, and the core MUST NOT compare versions.
- locked by
- 0.18.0 unmarked
- cited by
- lemonfiber@0a4ad43072
Every capability MUST be proved by a substitute other than its first-party filler, run end to end against its pinned upstream through install, its first-run flow, conformance, substitution, the features the capability serves, and undo.
- locked by
- 0.18.0 open
Every first-party plugin MUST live in a repository of its own, every first-party adapter MUST be built on the adapter kit, and every image a first-party plugin builds MUST be published from every commit on its repository's main and by the release train (OPS-R90).
- locked by
- 0.18.0 open
- recorded partial
- plugin-jellyfinCargo.tomlDockerfile.github/workflows/release.yml
An answer outside a contract MUST be recorded against the plugin with the capability, the operation, why and when, and a plugin recorded nonconforming for a capability MUST NOT fill it until it passes a live proof run after the record; updating it, installing it again and proving it again MUST each run that proof, and a passing proof MUST clear its records.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/app/plugins/reproving.rscrates/lemonfiber-core/src/app/plugins/tests/reproving.rs::an_update_proves_the_plugin_again_and_clears_what_was_keptcrates/lemonfiber-core/src/app/plugins/tests/reproving.rs::installing_again_proves_the_plugin_again_and_clears_what_was_kept
- cited by
- lemonfiber@00a691442flemonfiber@c16efaec03lemonfiber-web@ab6442ebe2
The installed plugins as lemonfiber plugin installed and GET /api/plugins answer them MUST name, for each plugin, every capability it is recorded nonconforming for, with the operation, why and when, and nothing a member is shown MUST name it.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/app/plugins/reproving.rscrates/lemonfiber-core/src/app/plugins/listing.rscrates/lemonfiber-core/src/app/plugins/tests/reproving.rs::the_installed_plugins_name_each_answer_kept_against_one_with_when_and_whycrates/lemonfiber/src/render/plugin/machine/tests/installed.rs::an_answer_kept_against_a_plugin_is_named_with_when_why_and_what_it_stopscrates/lemonfiber-api/tests/integration/what_a_client_is_told_it_may_do.rs::a_member_is_told_what_is_theirs_and_what_is_not
- cited by
- lemonfiber@c16efaec03
A credential lemonfiber holds MUST reach a plugin's service only where it is that plugin's own, where the plugin is first-party and the credential is the stack's, or where both the plugin and the credential's owner are first-party.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/wiring/fillers.rscrates/lemonfiber-core/src/wiring/fillers/tests.rs::a_credential_crosses_to_the_stack_its_own_plugin_and_first_party_alonecrates/lemonfiber-core/src/seed/run/connecting/tests.rs::every_connection_hands_a_credential_only_where_the_gate_lets_it_crosscrates/lemonfiber-core/src/settings/tests/files.rs::a_stack_credential_does_not_cross_to_a_plugin_nobody_vouched_for
- cited by
- lemonfiber@8d5d4bbb97lemonfiber@1879fda6a0lemonfiber@d24986d65dlemonfiber@dc6670838b
A plugin MUST be first-party only where the build embeds its id, the digest of its manifest and the digest of its tree in its first-party set, as the signed default bundle names them at the release the build pins; any other plugin MUST be third-party however it was installed.
- locked by
- 0.18.0 unmarked
- cited by
- lemonfiber@dc6670838b
A third-party plugin MAY be granted one named credential for a capability it fills; the grant MUST be part of the install or update offer and approved by the operator, MUST be journalled and revocable, and MUST be shown on the credentials surface, and without a grant no credential MUST cross to it.
- locked by
- 0.18.0 unmarked
- cited by
- lemonfiber@2b6555d0a0
An install or update whose plugin takes the egress guard's shape MUST state in its reading each service taking it with the capability and the device it is given, MUST NOT act unless the operator approved that shape for that service apart from the offer, written egress-guard@<service>, and MUST refuse an approval naming a service that does not take it.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/plugin/stating.rscrates/lemonfiber-core/src/plugin/stating/tests.rscrates/lemonfiber-core/src/app/plugins/offering.rscrates/lemonfiber/src/render/plugin/machine/answering.rscrates/lemonfiber/src/render/plugin/machine/answering/tests.rs
- cited by
- lemonfiber@0e9fbff3d7lemonfiber-web@88590bbc5d
A plugin's service MAY ask for a core capability in the manifest's [[ask]], naming the capability and optionally each; the manifest MUST have no field by which an ask names the service that fills it, and an ask naming a capability outside the published core vocabulary, a namespaced one included, naming a service the plugin does not declare, or naming a capability its own service provides MUST be refused at validation, naming the ask and what it named.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-plugin/src/refusing/asking.rscrates/lemonfiber-plugin/src/schema.rscrates/lemonfiber-plugin/src/refusing/asking/tests.rs::an_ask_carrying_a_service_to_reach_is_refused_by_the_schemacrates/lemonfiber-plugin/src/refusing/asking/tests.rs::an_ask_for_a_core_shaped_name_nothing_carries_is_refused_with_what_is_carriedcrates/lemonfiber-plugin/src/refusing/asking/tests.rs::an_ask_for_a_namespaced_capability_is_refused_as_naming_a_plugincrates/lemonfiber-plugin/src/refusing/asking/tests.rs::an_ask_naming_another_service_is_refused_naming_the_services_declaredcrates/lemonfiber-plugin/src/refusing/asking/tests.rs::a_service_asking_for_what_it_provides_is_refused
- cited by
- lemonfiber@cf9a18239d
A plugin's ask MUST be settled as the stack's own asks of that capability are: against every installed claimant, by the operator's choice where one is recorded, otherwise by the stack's own choice for that capability, and otherwise contested or unfilled; every connection made for it MUST hand a credential only where F14-R18 or F14-R20 lets it cross, and its asker MUST join exactly the network that ask derives (ARCH-R242) and no other on its account.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/wiring/settling.rscrates/lemonfiber-core/src/wiring/tests/asking.rs::a_plugins_ask_follows_the_stacks_and_says_whose_service_askedcrates/lemonfiber-core/src/wiring/tests/asking.rs::a_plugins_ask_for_one_of_several_takes_the_stacks_own_choice_and_its_reasoncrates/lemonfiber-core/src/wiring/tests/asking.rs::the_operators_choice_settles_a_plugins_ask_over_the_stackscrates/lemonfiber-core/src/wiring/tests/asking.rs::a_plugins_ask_the_stack_has_no_choice_for_stands_contestedcrates/lemonfiber-core/src/wiring/tests/asking.rs::a_plugins_ask_nothing_fills_is_reported_naming_the_plugins_servicecrates/lemonfiber-core/src/seed/run/connecting/tests.rs::every_connection_hands_a_credential_only_where_the_gate_lets_it_crosscrates/lemonfiber-core/src/project/tests.rs::a_plugin_services_ask_joins_it_to_that_asks_network_and_no_other
- cited by
- lemonfiber@cf9a18239d
The wiring, as lemonfiber wiring and GET /api/wiring answer it, MUST carry every installed plugin's asks after the stack's, each with the origin of the service that asks, and a plugin's asks MUST be counted wherever the stack's are: in what nothing fills, in what a substitution changes, and in what an install would leave contested.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/wiring/run.rscrates/lemonfiber-core/src/wiring/run/tests.rs::the_listing_carries_an_installed_plugins_ask_after_the_stacks_with_its_origincrates/lemonfiber-core/src/wiring/tests/asking.rs::a_plugins_ask_nothing_fills_is_reported_naming_the_plugins_servicecrates/lemonfiber-core/src/wiring/tests/asking.rs::a_capability_only_a_plugin_asks_for_can_be_chosen_and_names_the_plugins_servicecrates/lemonfiber-core/src/wiring/tests/asking.rs::installing_a_plugin_whose_ask_stands_contested_says_so_and_lists_its_asks_alone
- cited by
- lemonfiber@cf9a18239d
An install or update reading MUST state every ask the plugin's services would make, each with what it would reach and how that would be settled; its offer MUST be named over those asks as a part of its own, and an answer to a reading whose asks have since moved MUST be refused naming that part.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/plugin/reports.rscrates/lemonfiber-core/src/app/plugins/offering.rscrates/lemonfiber-core/src/wiring/tests/asking.rs::installing_a_plugin_whose_ask_stands_contested_says_so_and_lists_its_asks_alonecrates/lemonfiber-core/src/app/plugins/offering/tests.rs::an_install_or_update_whose_asks_moved_is_refused_naming_that_part_alone
- cited by
- lemonfiber@cf9a18239d
Where the media server is a plugin's service that speaks identity.source, its first-run setup MUST go over that contract with an administrator's password lemonfiber mints and keeps under that server's own setting, and the request service's identity setup MUST be given that password with the stack-network address and the native API of the service the adapter fronts; where that service declares no native API, the setup MUST NOT be attempted and the run MUST say so, naming the plugin.
- locked by
- 0.18.0 unmarked
- cited by
- lemonfiber@fe8607ed4f
lemonfiber MUST write the entry of every plugin service that speaks a contract to run as the operator's uid and gid, as the stack's own images run, and MUST write the key it asks that service with readable by that uid alone; a service that speaks none MUST be written with the user its user_mode names (ARCH-R233).
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/app/plugins/writing.rscrates/lemonfiber-core/src/app/plugins/tests/writing.rs::an_adapters_key_is_minted_once_kept_after_and_never_made_up
- recorded partial
- plugin-jellyfinDockerfile.github/workflows/adapter.yml
- cited by
- lemonfiber@9666b9962dlemonfiber@70bc2e0378
Where an adapter's upstream needs a credential lemonfiber keeps, lemonfiber MUST be the only writer of it: it MUST write it into the adapter's configuration directory as upstream.json, a JSON object of named strings readable by the operator's uid alone, whenever it creates, rotates or moves that credential, and the adapter MUST read it there and MUST NOT write it.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/app/targets/media.rscrates/lemonfiber-adapter-kit/src/lib.rscrates/lemonfiber-adapter-kit/src/tests.rs::the_upstreams_credential_is_read_afresh_from_where_the_core_wrote_itcrates/lemonfiber-core/src/app/targets/media/tests.rs::a_contracted_servers_password_is_handed_to_its_adaptercrates/lemonfiber-core/src/app/credentials/rotating/tests.rs::a_contracted_servers_administrator_password_rotates_over_its_contractcrates/lemonfiber-core/src/seed/run/tests/identity.rs::a_recorded_password_is_handed_to_the_adapter_and_a_rehearsal_hands_nothingcrates/lemonfiber/tests/architecture/an_adapter_only_reads_its_upstreams_credential.rs::the_adapter_kit_writes_no_file
- recorded partial
- plugin-jellyfinsrc/credential.rssrc/credential/tests.rs::the_file_lemonfiber_wrote_is_read_as_the_credential
- cited by
- lemonfiber@9666b9962dlemonfiber@e2005b9828lemonfiber@03fffb49ealemonfiber@14dd55adf9lemonfiber@70bc2e0378
An install or update MUST honour a service's replaces only where the plugin is first-party, moving the service the bundle reserves under that id in place under the same container name, configuration directory and data; a third-party plugin declaring replaces MUST be refused at install and update, naming the service.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/plugin/first_party.rscrates/lemonfiber-core/src/app/plugins/tests/writing.rs::only_a_first_party_plugin_replaces_a_stack_servicecrates/lemonfiber-core/src/project/tests.rs::a_stack_service_moved_in_place_is_left_out_and_its_stand_in_writtencrates/lemonfiber-core/src/project/tests.rs::only_a_first_party_service_taking_its_id_moves_in_place_of_a_stack_service
- cited by
- lemonfiber@bd04cd45e7
Where the media server is a plugin's service that speaks identity.source, rotating its administrator's password MUST go over that contract: lemonfiber MUST record the replacement under the server's pending setting before asking, MUST hand the adapter the replacement alone, MUST promote it and rewrite the adapter's upstream credential only once the adapter answers that the server took it, and MUST leave the password in force unchanged wherever the adapter refuses.
- locked by
- 0.18.0 met
- recorded done
- lemonfibercrates/lemonfiber-core/src/app/credentials/rotating.rscrates/lemonfiber-core/src/app/credentials/rotating/tests.rs::a_replacement_the_adapter_refuses_leaves_the_password_in_forcecrates/lemonfiber-core/src/app/credentials/rotating/tests.rs::a_replacement_the_adapter_cannot_settle_is_kept_pending_as_it_was_sent
- cited by
- lemonfiber@03fffb49ea