Drop the invented layer taxonomy from OVERVIEW.md
The overview had been restructured around a named three-layer model — user, developer, filesystem — that was never part of the design. The underlying point stands: a reader must be able to tell whether a given statement applies to them, and a code-level symbol must never appear in prose without saying whose vantage point it belongs to. Sections are now named for the reader they address rather than for a tier: "Running the dpm binary", "Writing a program against libdpm-core", "What DPM reads and writes on disk". The remaining uses of "layer" are the capability-growth layers the design already defines. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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.
|
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
|
## Running the dpm binary
|
||||||
|
|
||||||
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 `<dpm/core.h>`, 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
|
|
||||||
|
|
||||||
The dpm binary's subcommand surface is exactly the set of loadable modules. `dpm <module> <command> [args...]` loads that module and hands the command to it; `dpm <module> 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.
|
The dpm binary's subcommand surface is exactly the set of loadable modules. `dpm <module> <command> [args...]` loads that module and hands the command to it; `dpm <module> 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.
|
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 `<dpm/core.h>`. Everything it does happens through a **context**, an opaque handle obtained from `dpm_open`.
|
A program links libdpm-core and includes `<dpm/core.h>`. 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.
|
**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.
|
**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
|
## 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.
|
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.
|
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
|
## 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
|
### 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
|
### Because nothing may be trusted that has not been verified
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user