diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index 71274a1..7763d1b 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -25,17 +25,7 @@ libdpm-core implements no package operations. It routes and hosts. Everything passes through libdpm-core: binary-to-module, module-to-module, program-to-module. No consumer performs module discovery or dynamic loading itself. -## Three layers to read this at - -DPM is met at three different layers, and which one you are at determines what any statement below means for you. - -- **The user layer** — a person at a shell running the dpm binary. Everything here is a command and its flags. -- **The developer layer** — a program written against the C API in ``, linking `-ldpm-core`. Everything here is a function call. Module authors live here too, on the other side of the same boundary. -- **The filesystem layer** — the directories and files DPM reads and writes: configuration, the module directory, the target root, and the installed artifacts. - -The sections that follow are labelled by layer. Where a mechanism exists at more than one layer, it is described once at each, because the same idea looks different depending on where you stand. - -## How it works at the user layer +## Running the dpm binary The dpm binary's subcommand surface is exactly the set of loadable modules. `dpm [args...]` loads that module and hands the command to it; `dpm help` asks the module to describe itself. There is no fixed list of operations baked into the tool, because the tool contains no capability logic — it parses arguments and prints. @@ -50,7 +40,7 @@ Four flags redirect the system defaults: These four exist because of a rule the design imposes on itself: every field a linked program can override must also be a flag, so anything reachable from code is reachable from a shell. That rule holds for any override added in the future. -## How it works at the developer layer +## Writing a program against libdpm-core A program links libdpm-core and includes ``. Everything it does happens through a **context**, an opaque handle obtained from `dpm_open`. @@ -73,7 +63,7 @@ The context owns everything it hands out. Every string a caller receives stays v **Services.** A module reaches libdpm-core through the context that dispatched the call: `dpm_log` to write a message, `dpm_config_get` to read a value from its own configuration namespace, `dpm_module_path` to learn where modules live, `dpm_core_version` to learn the library's version. A module needs no file handling and no logging machinery of its own. -## How it works at the filesystem layer +## What DPM reads and writes on disk **Configuration** lives in `/etc/dpm/conf.d/`. Each `.conf` file in that directory is one namespace named after the file: `core.conf` holds the library's own settings, and a module named `mymodule` reads `mymodule.conf`. Files are sectioned, and a value is addressed by namespace, section, and key. The library's own file carries the log level, whether to write a log file and where, and the default module directory. @@ -94,7 +84,7 @@ The context owns everything it hands out. Every string a caller receives stays v ## The module contract -*Developer layer, module-author side.* +*What a module author implements.* A module is one `.so` in the module directory exporting five reserved symbols: a command entry point, its own version, a one-line description, the minimum libdpm-core version it supports, and a manifest. The manifest declares the module's entire functional surface — for each API, its name, table version, and the exact exported symbol carrying the table. @@ -112,7 +102,7 @@ libdpm-core validates a module completely before offering it to anyone, in five A module failing any step is refused with an itemized reason and its library handle closed. Validation is all-or-nothing: if a handle comes back, the contract already passed. Consumers never defend against partially valid modules, because they cannot receive one. -At the user layer this is visible as a module missing from `--list-modules` with a logged reason, or as an itemized failure when the module is named directly. +From the command line this shows up as a module missing from `--list-modules` with a logged reason, or as an itemized failure when the module is named directly. ## Versioning @@ -134,7 +124,7 @@ Each layer of the system installs the dependencies of the next using only what a ### Because one implementation must serve every caller -The requirement that every implementation exist exactly once, and be consumable by the dpm binary, by other layers, and by external programs, is what makes libdpm-core a C ABI library rather than an application with a library carved out of it. This is also why the user layer and the developer layer stay in step: the flags are the override fields, one for one, so a developer and a user redirect the same things by the same names. +The requirement that every implementation exist exactly once, and be consumable by the dpm binary, by other layers, and by external programs, is what makes libdpm-core a C ABI library rather than an application with a library carved out of it. It is also why the command line and the C API stay in step: the flags are the override fields, one for one, so a program and a person redirect the same things by the same names. ### Because nothing may be trusted that has not been verified