docs+build: correct version drift, mangled prose, and toolchain-version gaps
Docs:
- Baseline was stated as 0.3.1 across the canonical set while the branch,
Cat 0/1 crates and every Cat 2 fork are 0.3.2. AGENTS.md also cited a
sources/redbear-0.3.1/ archive that does not exist; the only archive
present is sources/redbear-0.1.0/. Versioning examples now match the
forks as they actually stand (redoxfs/syscall 0.9.1, libredox 0.1.19).
- Repaired 18 instances of 'immutable archived' across 8 documents, where
a global find/replace had turned sync/synced/archived into that phrase
and produced ungrammatical text ('never auto-immutable archived',
'### Source immutable archived').
- Settled the apply-patches.sh contradiction empirically. Both sides were
wrong: the GROSS WARNING blocks (x5) described it as routine
patch-linking, and SCRIPT-BEHAVIOR-MATRIX.md said build-redbear.sh
'never invokes' it. It is invoked at build-redbear.sh:487, but only to
auto-repair a failed verify-overlay-integrity.sh check.
- Dropped the dangling reference to a local/AGENTS.md section
'NO OVERLAY-STYLE PATCHES — SCOPED POLICY' that does not exist.
Build system:
- mk/prefix.mk hardcoded 13.2.0 in the limits.h removal, which silently
no-ops after a toolchain upgrade and leaves the conflicting header.
Version-globbed.
- Parameterized GCC_RECIPE so the from-source toolchain path is not
pinned to gcc13.
- The three cstdlib strtold seds were not idempotent -- the shipped GCC
13 toolchain carried that comment block 17 times from repeated
'make prefix' runs. Each is now guarded.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
## Canonical build — do NOT bypass
|
||||
|
||||
> ⚠️ **GROSS WARNING — DO NOT run `repo cook`, `repo fetch`, or `make live` directly.**
|
||||
> These bypass the canonical build pipeline (`apply-patches.sh` patch-linking + staleness handling + correct dependency ordering), which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
> These bypass the canonical build pipeline — the concurrency lock, the dirty-source and fork-branch gates, prefix-staleness detection and rebuild, overlay-integrity verification (which auto-repairs recipe symlinks via `apply-patches.sh` when it fails), source-fingerprint tracking, and correct dependency ordering — which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
|
||||
## OVERVIEW
|
||||
|
||||
@@ -17,7 +17,7 @@ into a bootable Redox image. Uses a Makefile + Rust "cookbook" tool + TOML confi
|
||||
Languages: Rust (core), C (ported packages), TOML (config), Make (build orchestration).
|
||||
|
||||
RedBearOS is a **full fork** of Redox OS — based on frozen, archived source snapshots.
|
||||
Sources are immutable and never auto-immutable archived from upstream. All changes are explicit,
|
||||
Sources are immutable and are never auto-synced from upstream. All changes are explicit,
|
||||
human-initiated operations. Durable Red Bear state belongs in `local/patches/`,
|
||||
`local/recipes/`, `local/docs/`, and tracked Red Bear configs.
|
||||
|
||||
@@ -39,8 +39,10 @@ No "this seems too heavy for mini". **When in doubt: KEEP IT AND FIX IT.**
|
||||
This rule exists because agents have repeatedly destroyed months of work by deciding
|
||||
packages were "unnecessary" and silently removing them during syncs and config changes.
|
||||
|
||||
The current baseline is **Red Bear OS 0.3.1** (Redox snapshot at build-system commit `f55acba68`).
|
||||
All recipe sources are pinned and archived in `sources/redbear-0.1.0/`.
|
||||
The current baseline is **Red Bear OS 0.3.2** (development branch `0.3.2`).
|
||||
`sources/redbear-0.1.0/` (Redox snapshot at build-system commit `f55acba68`) is the last
|
||||
frozen release archive and is **not** the current source of truth — the current branch builds
|
||||
from the `local/sources/<component>/` forks. It is the only archive present in `sources/`.
|
||||
|
||||
## STRUCTURE
|
||||
|
||||
@@ -608,15 +610,18 @@ Round 14). Git hook details are documented in `local/docs/RELEASE-BUMP-WORKFLOW.
|
||||
### Offline-First By Default
|
||||
|
||||
Red Bear OS is a **fork with frozen sources**. The cookbook tool defaults to
|
||||
`COOKBOOK_OFFLINE=true` (changed from upstream Redox's `false`). Builds use archived
|
||||
sources from `sources/redbear-0.3.1/` — no network access during compilation.
|
||||
`COOKBOOK_OFFLINE=true` (changed from upstream Redox's `false`). Builds resolve sources
|
||||
locally — from the `local/sources/` forks on a development branch, or from
|
||||
`sources/redbear-<release>/` in release mode — with no network access during compilation.
|
||||
`sources/redbear-0.1.0/` is currently the only archive present.
|
||||
|
||||
To allow online fetching for non-protected development recipes, use the `--upstream` flag:
|
||||
```bash
|
||||
./local/scripts/build-redbear.sh --upstream redbear-mini
|
||||
```
|
||||
|
||||
In release mode (`REDBEAR_RELEASE=0.3.1`), online fetching is **completely disabled**
|
||||
In release mode (e.g. `REDBEAR_RELEASE=0.1.0`, matching an archive that exists under
|
||||
`sources/`), online fetching is **completely disabled**
|
||||
even with `COOKBOOK_OFFLINE=false`. Sources are immutable in release mode.
|
||||
|
||||
**For development with local forks** (see "LOCAL FORK MODEL" in `local/AGENTS.md`),
|
||||
@@ -690,7 +695,7 @@ Critical rules:
|
||||
After ANY change to patches or `recipe.toml`:
|
||||
|
||||
> ⚠️ **GROSS WARNING — DO NOT run `repo cook`, `repo fetch`, or `make live` directly.**
|
||||
> These bypass the canonical build pipeline (`apply-patches.sh` patch-linking + staleness handling + correct dependency ordering), which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
> These bypass the canonical build pipeline — the concurrency lock, the dirty-source and fork-branch gates, prefix-staleness detection and rebuild, overlay-integrity verification (which auto-repairs recipe symlinks via `apply-patches.sh` when it fails), source-fingerprint tracking, and correct dependency ordering — which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
|
||||
1. Validate patches: `./target/release/repo validate-patches <recipe>`
|
||||
2. Remove source: `rm -rf recipes/core/<recipe>/source`
|
||||
@@ -839,8 +844,10 @@ local/patches/
|
||||
|
||||
### Release Model (Fork)
|
||||
|
||||
Red Bear OS is a full fork based on frozen Redox snapshots. Sources are immutable
|
||||
and never auto-immutable archived. The current baseline is 0.3.1 (sources archive at sources/redbear-0.1.0/ is the LAST frozen release; current branch builds from local/sources/ forks).
|
||||
Red Bear OS is a full fork based on frozen Redox snapshots. Sources are immutable and are
|
||||
never refreshed from upstream automatically. The current baseline is 0.3.2; the archive at
|
||||
`sources/redbear-0.1.0/` is the last frozen release, and the current branch builds from the
|
||||
`local/sources/` forks.
|
||||
|
||||
```bash
|
||||
# Check for newer Redox snapshots (read-only, zero side effects):
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ relibc, drivers, system utilities) live here as submodule branches or tracked tr
|
||||
- **Chat** — upstream Redox has [Matrix](https://matrix.to/#/#redox-join:matrix.org) and
|
||||
[Discord](https://discord.gg/JfggvrHGDY) rooms. Red Bear contributors are welcome there,
|
||||
but issue tracking happens on Gitea, not in chat.
|
||||
- **Merge requests** — open MRs on Gitea against the `0.3.1` branch. Small MRs review faster
|
||||
- **Merge requests** — open MRs on Gitea against the current release branch (`0.3.2`). Small MRs review faster
|
||||
than large ones; split big work into reviewable slices.
|
||||
|
||||
---
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
## What is Red Bear OS?
|
||||
|
||||
Red Bear OS is a general-purpose, Unix-like operating system with a **microkernel architecture**,
|
||||
written entirely in **Rust**. It is a full fork of Redox OS (baseline 0.3.1), actively developed
|
||||
on branch `0.3.1` with hardware enablement, multiple filesystems, a native greeter and login
|
||||
written entirely in **Rust**. It is a full fork of Redox OS (baseline 0.3.2), actively developed
|
||||
on branch `0.3.2` with hardware enablement, multiple filesystems, a native greeter and login
|
||||
system, and a KDE Plasma desktop path.
|
||||
|
||||
We aim to stay close to upstream Redox — diverging only where necessary to add missing
|
||||
@@ -118,7 +118,7 @@ make qemu
|
||||
|
||||
Red Bear OS **boots to a login prompt** in QEMU with working wired networking, D-Bus system bus,
|
||||
hardware detection daemons, and three filesystem backends (RedoxFS, ext4, FAT). The ISO builds
|
||||
successfully on branch `0.3.1`. Graphics packages are frozen at latest upstream stable
|
||||
successfully on branch `0.3.2`. Graphics packages are frozen at latest upstream stable
|
||||
(Qt 6.11.1, KF6 6.27.0, Plasma 6.7.2, SDDM 0.21.0, Mesa 26.1.4, wayland-protocols 1.49).
|
||||
|
||||
| Area | Status |
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
Build this repository using the Red Bear release fork model:
|
||||
|
||||
- sources are frozen, immutable release snapshots at baseline 0.3.1,
|
||||
- sources are frozen, immutable release snapshots at baseline 0.3.2,
|
||||
- durable Red Bear state lives in `local/patches/`, `local/recipes/`, `local/docs/`, and tracked
|
||||
Red Bear configs,
|
||||
- build from archived sources offline by default; provision new releases explicitly via provision-release.sh.
|
||||
@@ -227,7 +227,7 @@ sudo dd if=build/x86_64/harddrive.img of=/dev/sdX bs=4M status=progress
|
||||
|
||||
Under the Red Bear release fork model, remember:
|
||||
|
||||
- `recipes/*/source/` is an immutable archived release snapshot,
|
||||
- `recipes/*/source/` is an immutable, archived release snapshot,
|
||||
- Red Bear-owned shipping deltas should be preserved under `local/patches/` and `local/recipes/`,
|
||||
- sources are built offline by default; provision new releases via provision-release.sh.
|
||||
|
||||
|
||||
@@ -29,18 +29,18 @@ relates to Debian.
|
||||
|
||||
- Redox is upstream.
|
||||
- Red Bear carries integration, packaging, validation, and subsystem release fork on top.
|
||||
- Upstream-owned source trees are immutable archived release snapshot.
|
||||
- Upstream-owned source trees are immutable, archived release snapshots.
|
||||
- Durable Red Bear state belongs in `local/patches/`, `local/recipes/`, `local/docs/`, and tracked
|
||||
Red Bear configs.
|
||||
|
||||
The project is in the right long-term shape only when immutable archived upstream sources can be fetched,
|
||||
The project is in the right long-term shape only when archived upstream sources can be fetched,
|
||||
Red Bear release fork can be apply, and the project still rebuilds successfully.
|
||||
|
||||
## Ownership Rules
|
||||
|
||||
### Upstream-owned layer
|
||||
|
||||
These are immutable archived release sources, not durable Red Bear storage:
|
||||
These are immutable, archived release sources, not durable Red Bear storage:
|
||||
|
||||
- `recipes/*/source/`
|
||||
- most of `recipes/` outside local release fork symlinks
|
||||
@@ -159,7 +159,7 @@ The current evidence-backed baseline is:
|
||||
- major local subsystem plans exist under `local/docs/`,
|
||||
- native wired networking is present,
|
||||
- Qt6 and major downstream desktop dependencies build,
|
||||
- Wayland-facing relibc compatibility surfaces now rebuild from a immutable archived upstream relibc source
|
||||
- Wayland-facing relibc compatibility surfaces now rebuild from an archived upstream relibc source
|
||||
tree via local patch carriers,
|
||||
- `libwayland` and `qtbase` build successfully from the reconstructed relibc state,
|
||||
- the Red Bear-native greeter/login path now has a bounded passing runtime proof, while broader KDE/KWin session stability is still not yet a general runtime claim,
|
||||
|
||||
+2
-2
@@ -21,11 +21,11 @@ current/canonical versus historical/reference split obvious.
|
||||
> **Repository model:** RedBearOS relates to Redox in the same way Ubuntu relates to Debian.
|
||||
> Upstream Redox remains the base platform; Red Bear carries packaging, patch, validation, and
|
||||
> subsystem release fork on top. For long-term stability, upstream-owned source trees should be treated
|
||||
> as immutable archived release snapshot, while durable Red Bear state belongs in `local/patches/`,
|
||||
> as immutable, archived release snapshots, while durable Red Bear state belongs in `local/patches/`,
|
||||
> `local/recipes/`, `local/docs/`, and tracked Red Bear configs.
|
||||
>
|
||||
> **WIP policy:** if an upstream recipe or subsystem is still marked WIP, Red Bear treats it as a
|
||||
> local project until upstream promotes it to first-class status. We may immutable archived from upstream WIP,
|
||||
> local project until upstream promotes it to first-class status. We may sync from upstream WIP,
|
||||
> but we should fix and ship from the Red Bear release fork until upstream support is real enough to
|
||||
> replace the local copy.
|
||||
|
||||
|
||||
+25
-24
@@ -6,7 +6,7 @@ updates (`git pull` on the build system repo), this directory is untouched.
|
||||
## Canonical build — do NOT bypass
|
||||
|
||||
> ⚠️ **GROSS WARNING — DO NOT run `repo cook`, `repo fetch`, or `make live` directly.**
|
||||
> These bypass the canonical build pipeline (`apply-patches.sh` patch-linking + staleness handling + correct dependency ordering), which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
> These bypass the canonical build pipeline — the concurrency lock, the dirty-source and fork-branch gates, prefix-staleness detection and rebuild, overlay-integrity verification (which auto-repairs recipe symlinks via `apply-patches.sh` when it fails), source-fingerprint tracking, and correct dependency ordering — which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
|
||||
## STUB AND WORKAROUND POLICY — ZERO TOLERANCE
|
||||
|
||||
@@ -41,9 +41,9 @@ files, Wayland protocol stubs, D-Bus service stubs, and any other layer of the s
|
||||
|
||||
Red Bear OS is a **full fork** based on frozen Redox OS snapshots:
|
||||
- We baseline on a specific Redox OS state and work from immutable, archived sources
|
||||
- The `local/` directory contains our custom work — untouched by any source immutable archived
|
||||
- The `local/` directory contains our custom work — untouched by any source sync
|
||||
- First-class configs use `redbear-*` naming (not `my-*`, which is gitignored)
|
||||
- Sources are NEVER auto-immutable archived from upstream — all changes are explicit, human-initiated
|
||||
- Sources are NEVER auto-synced from upstream — all changes are explicit, human-initiated
|
||||
|
||||
## LOCAL FORK SUPREMACY POLICY (ABSOLUTE)
|
||||
|
||||
@@ -173,7 +173,7 @@ The **only** branches that exist in the `RedBear-OS` repo are:
|
||||
|
||||
| Branch type | Examples | Who creates them |
|
||||
|---|---|---|
|
||||
| **Release branches** | `master`, `0.2.0`, `0.2.1`, …, `0.3.1`, … | **Operator only**, one per Red Bear OS release cycle. |
|
||||
| **Release branches** | `master`, `0.2.0`, `0.2.1`, …, `0.3.1`, `0.3.2`, … | **Operator only**, one per Red Bear OS release cycle. |
|
||||
| **Submodule branches** | `submodule/base`, `submodule/kernel`, `submodule/relibc`, … (9 total) | **Operator only**, one per forked upstream component. |
|
||||
| **Recovery branches** | `recovered/quirks` | **Operator only**, for emergency recovery work. |
|
||||
|
||||
@@ -187,7 +187,7 @@ Agents **MUST NOT**:
|
||||
explicitly decided to fork a new upstream component.
|
||||
|
||||
**If you need to work on a change, commit to the branch you are already on.**
|
||||
Release work goes on the current release branch (e.g. `0.3.1`). Fork changes
|
||||
Release work goes on the current release branch (e.g. `0.3.2`). Fork changes
|
||||
go on the appropriate `submodule/<component>` branch. There is no
|
||||
justification for a new branch — use a commit, a patch file, or a tracked
|
||||
tree instead.
|
||||
@@ -750,7 +750,7 @@ Red Bear OS has exactly two version categories:
|
||||
|
||||
These are original Red Bear projects (tlc, cub, redbear-*, etc.) with no
|
||||
upstream. Their version **MUST** be the current Red Bear OS branch version
|
||||
(e.g. `0.3.1` on branch `0.3.1`).
|
||||
(e.g. `0.3.2` on branch `0.3.2`).
|
||||
|
||||
**Category 2 (Cat 2) — Upstream Redox forks** (`local/sources/*/`):
|
||||
|
||||
@@ -763,19 +763,20 @@ resolution while still marking the fork as Red Bear's:
|
||||
<upstream-version>+rb<RedBear-OS-branch-version>
|
||||
```
|
||||
|
||||
For example, on branch `0.3.1`:
|
||||
- `redoxfs` tracking upstream `0.9.0` → `version = "0.9.0+rb0.3.1"`
|
||||
- `kernel` tracking upstream `0.5.12` → `version = "0.5.12+rb0.3.1"`
|
||||
- `syscall` tracking upstream `0.9.0` → `version = "0.9.0+rb0.3.1"`
|
||||
For example, on branch `0.3.2`:
|
||||
- `redoxfs` tracking upstream `0.9.1` → `version = "0.9.1+rb0.3.2"`
|
||||
- `kernel` tracking upstream `0.5.12` → `version = "0.5.12+rb0.3.2"`
|
||||
- `syscall` tracking upstream `0.9.1` → `version = "0.9.1+rb0.3.2"`
|
||||
- `libredox` tracking upstream `0.1.19` → `version = "0.1.19+rb0.3.2"`
|
||||
|
||||
The `-rb` suffix MUST NOT be used in `Cargo.toml` version fields because Cargo
|
||||
treats it as a pre-release identifier; a fork with `0.9.0-rb0.3.1` would not
|
||||
treats it as a pre-release identifier; a fork with `0.9.1-rb0.3.2` would not
|
||||
satisfy upstream transitive dependency requirements such as `^0.9.0`. The `+rb`
|
||||
build-metadata suffix leaves the upstream version intact (`0.9.0`) so that
|
||||
`[patch.crates-io]` and transitive crates.io dependencies resolve correctly.
|
||||
|
||||
When the Red Bear OS branch changes (e.g. `0.3.1` → `0.2.6`), **all** Cat 2
|
||||
fork versions automatically bump their suffix: `0.9.0+rb0.3.1` → `0.9.0+rb0.2.6`.
|
||||
When the Red Bear OS branch changes (e.g. `0.3.1` → `0.3.2`), **all** Cat 2
|
||||
fork versions automatically bump their suffix: `0.9.1+rb0.3.1` → `0.9.1+rb0.3.2`.
|
||||
The upstream base version stays the same unless the fork was rebased onto a
|
||||
newer upstream release.
|
||||
|
||||
@@ -789,8 +790,8 @@ newer upstream release.
|
||||
```
|
||||
|
||||
`sync-versions.sh` handles BOTH categories in one pass:
|
||||
- Cat 1: sets `version = "<branch>"` (e.g. `0.3.1`)
|
||||
- Cat 2: sets `version = "<upstream-base>+rb<branch>"` (e.g. `0.9.0+rb0.3.1`)
|
||||
- Cat 1: sets `version = "<branch>"` (e.g. `0.3.2`)
|
||||
- Cat 2: sets `version = "<upstream-base>+rb<branch>"` (e.g. `0.9.0+rb0.3.2`)
|
||||
|
||||
The `--check` mode is suitable for CI gates and preflight checks.
|
||||
|
||||
@@ -968,12 +969,12 @@ The `version = "X.Y.Z+rbB.B.B"` field in a Cat 2 fork's `Cargo.toml` MUST accura
|
||||
describe the underlying source code. Specifically:
|
||||
|
||||
- The `<X.Y.Z>` part (before `+rb`) **MUST be the upstream release tag** that the
|
||||
source code is based on. Setting `version = "0.9.0+rb0.3.1"` on a fork whose
|
||||
source code is based on. Setting `version = "0.9.0+rb0.3.2"` on a fork whose
|
||||
source code is actually upstream `0.8.x` (or any other version) is a **fake
|
||||
label** and a **policy violation**. The `+rbB.B.B` suffix is meaningful only
|
||||
when applied to the correct upstream base.
|
||||
- The `+rbB.B.B` part (after `+rb`) **MUST be the current Red Bear OS branch
|
||||
version**. On branch `0.3.1`, every Cat 2 fork MUST use `+rb0.3.1`. This makes
|
||||
version**. On branch `0.3.2`, every Cat 2 fork MUST use `+rb0.3.2`. This makes
|
||||
it trivial to trace which Red Bear branch a fork was built for.
|
||||
- The fork's source code **MUST be a real rebase onto upstream `<X.Y.Z>`** plus
|
||||
Red Bear patches, NOT a mislabeled old version of the upstream code with the
|
||||
@@ -1006,7 +1007,7 @@ describe the underlying source code. Specifically:
|
||||
|
||||
```
|
||||
local/sources/redoxfs/
|
||||
├── Cargo.toml # version = "0.9.0+rb0.3.1" (upstream 0.9.0 + branch 0.3.1)
|
||||
├── Cargo.toml # version = "0.9.1+rb0.3.2" (upstream 0.9.1 + branch 0.3.2)
|
||||
├── Cargo.toml.orig # mirrors upstream, regenerated for cargo consistency
|
||||
├── src/... # the upstream 0.9.0 source tree, byte-for-byte
|
||||
└── local/patches/redoxfs/ # Red Bear patches, each one small and reviewable
|
||||
@@ -1022,14 +1023,14 @@ only difference from upstream — that would be a fake label.
|
||||
|
||||
**What a fake label looks like (REJECTED):**
|
||||
|
||||
- A fork whose `Cargo.toml` says `0.9.0+rb0.3.1` but whose source content is
|
||||
- A fork whose `Cargo.toml` says `0.9.0+rb0.3.2` but whose source content is
|
||||
upstream `0.8.6` (a different version).
|
||||
- A fork whose `Cargo.toml` says `0.9.0+rb0.3.1` but whose dep constraints
|
||||
- A fork whose `Cargo.toml` says `0.9.0+rb0.3.2` but whose dep constraints
|
||||
(`redox_syscall = "0.7.0"`, `libredox = "0.1.12"`, etc.) reference versions
|
||||
that don't match upstream 0.9.0's ecosystem.
|
||||
- A fork whose `+rb` suffix doesn't match the current branch (e.g.
|
||||
`+rb0.2.4` while on branch `0.3.1`).
|
||||
- A fork whose only commit is "fork: bump to +rb0.3.1 version suffix" with no
|
||||
`+rb0.2.4` while on branch `0.3.2`).
|
||||
- A fork whose only commit is "fork: bump to +rb0.3.2 version suffix" with no
|
||||
actual rebasing onto the matching upstream tag.
|
||||
|
||||
All of these are caught by the enforcement script and the build aborts
|
||||
@@ -1342,7 +1343,7 @@ redox-master/ ← git pull updates mainline Redox
|
||||
## HOW TO BUILD RED BEAR OS
|
||||
|
||||
> ⚠️ **GROSS WARNING — DO NOT run `repo cook`, `repo fetch`, or `make live` directly.**
|
||||
> These bypass the canonical build pipeline (`apply-patches.sh` patch-linking + staleness handling + correct dependency ordering), which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
> These bypass the canonical build pipeline — the concurrency lock, the dirty-source and fork-branch gates, prefix-staleness detection and rebuild, overlay-integrity verification (which auto-repairs recipe symlinks via `apply-patches.sh` when it fails), source-fingerprint tracking, and correct dependency ordering — which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
|
||||
```bash
|
||||
# CANONICAL build command — produces a live ISO for bare metal
|
||||
@@ -1783,7 +1784,7 @@ See `local/docs/BUILD-SYSTEM-INVARIANTS.md` for invariants I1-I3.
|
||||
- **DO NOT** assume mainline recipe names won't conflict — prefix custom ones (e.g., `redox-`)
|
||||
- **DO NOT** use `my-*` naming for configs that should be tracked in git — use `redbear-*` instead
|
||||
- **DO NOT** edit config/base.toml directly — our configs include it and override via TOML merge
|
||||
- **DO NOT** attempt to immutable archived sources from upstream — sources are immutable; use provision-release.sh
|
||||
- **DO NOT** attempt to sync sources from upstream — sources are immutable; use provision-release.sh
|
||||
|
||||
## COMPREHENSIVE IMPLEMENTATION POLICY
|
||||
|
||||
|
||||
@@ -175,9 +175,9 @@ cooks the tree as-is. A read-only startup advisory reports any leftover
|
||||
`recipes/<fork>/`. Version policy (`sync-versions.sh`):
|
||||
|
||||
- **Cat 1** — in-house crates under `local/recipes/*/source/`: `version = <branch>`
|
||||
(e.g. `0.3.1`).
|
||||
(e.g. `0.3.2`).
|
||||
- **Cat 2** — upstream forks under `local/sources/*/`:
|
||||
`version = <upstream-tag>+rb<branch>` (e.g. `0.9.0+rb0.3.1`; `+rb` build
|
||||
`version = <upstream-tag>+rb<branch>` (e.g. `0.9.0+rb0.3.2`; `+rb` build
|
||||
metadata, never `-rb`).
|
||||
- **Vendored upstream** under `local/recipes/` (e.g. `brush`, a Cargo workspace):
|
||||
keeps its **upstream** crate versions (internal `^` requirements). Mark it with
|
||||
|
||||
@@ -23,7 +23,7 @@ of functionality our system needs, implemented in our tree, maintained by us.
|
||||
### What Red Bear OS Is
|
||||
|
||||
Red Bear OS is a **full fork** of Redox OS, based on frozen Redox snapshots
|
||||
(currently branch `0.3.1`; legacy release archive at `sources/redbear-0.1.0/`
|
||||
(currently branch `0.3.2`; legacy release archive at `sources/redbear-0.1.0/`
|
||||
at build-system commit `f55acba68`). We are NOT a downstream
|
||||
distributor of Redox. We are NOT a configuration overlay on top of Redox.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ When reordering patches, test the FULL chain: remove source, rebuild, verify.
|
||||
|
||||
`recipes/core/base/recipe.toml` is git-tracked. Changes to it are durable.
|
||||
`recipes/core/base/source/` is a fetched working copy — destroyed by `make clean`,
|
||||
`make distclean`, source immutable archived, and provision-release.
|
||||
`make distclean`, source re-sync, and provision-release.
|
||||
|
||||
Any change to source/ MUST be preserved as a patch in `local/patches/base/`.
|
||||
|
||||
@@ -76,7 +76,7 @@ implemented work to bypass build failures.
|
||||
After ANY change to the patches list or patch files:
|
||||
|
||||
> ⚠️ **GROSS WARNING — DO NOT run `repo cook`, `repo fetch`, or `make live` directly.**
|
||||
> These bypass the canonical build pipeline (`apply-patches.sh` patch-linking + staleness handling + correct dependency ordering), which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
> These bypass the canonical build pipeline — the concurrency lock, the dirty-source and fork-branch gates, prefix-staleness detection and rebuild, overlay-integrity verification (which auto-repairs recipe symlinks via `apply-patches.sh` when it fails), source-fingerprint tracking, and correct dependency ordering — which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
|
||||
1. Remove the source tree: `rm -rf recipes/core/base/source`
|
||||
2. Full rebuild: `REDBEAR_ALLOW_PROTECTED_FETCH=1 CI=1 make r.base`
|
||||
|
||||
@@ -11,21 +11,20 @@ The goal is to remove guesswork from the sync/fetch/apply/build workflow.
|
||||
> The "release fork" in this document refers to Red Bear's owned code in
|
||||
> `local/sources/`, `local/recipes/`, `config/redbear-*.toml`, and
|
||||
> `local/patches/<component>/` (Rule 2 external patches for big external
|
||||
> projects). There is **no overlay layer** of `apply-patches.sh`-style
|
||||
> symlinks between `recipes/` and `local/recipes/`. See
|
||||
> `local/AGENTS.md` "NO OVERLAY-STYLE PATCHES — SCOPED POLICY" for the
|
||||
> two-rule model. Where this document references the historical
|
||||
> `apply-patches.sh` script, that is **legacy/archived** behavior; the
|
||||
> canonical build flow is `local/scripts/build-redbear.sh <profile>`,
|
||||
> which never invokes `apply-patches.sh`.
|
||||
> projects). The `recipes/<cat>/<name>` entries are symlinks into
|
||||
> `local/recipes/`, and `apply-patches.sh` is what (re)creates them. It is no
|
||||
> longer a routine build step: `build-redbear.sh` runs
|
||||
> `verify-overlay-integrity.sh` and calls `apply-patches.sh` **only to
|
||||
> auto-repair** when that check fails (`build-redbear.sh:487`). The canonical
|
||||
> build flow is `local/scripts/build-redbear.sh <profile>`.
|
||||
|
||||
## Matrix
|
||||
|
||||
| Script | Primary role | What it handles | What it does **not** guarantee |
|
||||
|---|---|---|---|
|
||||
| `local/scripts/provision-release.sh` | Refresh top-level upstream repo state | fetches upstream, reports conflict risk, rebases repo commits. Under v6.0 the "release fork reapplication" step is no longer needed because `local/sources/`, `local/recipes/`, and `local/patches/<component>/` already live in the main repo (Rule 1 + Rule 2). | does not automatically solve every subsystem release fork conflict; does not by itself make upstream WIP recipes safe shipping inputs |
|
||||
| `local/scripts/apply-patches.sh` | **LEGACY / ARCHIVED** — historical overlay only | under v5.x, applied build-system patches and relinked recipe patch symlinks; under v6.0 this is a no-op for in-tree components (Rule 1 direct edits) and is replaced by `cookbook_apply_patches` for big external projects (Rule 2). See `local/AGENTS.md`. | do not invoke during a v6.0 build. The `local/scripts/build-redbear.sh <profile>` canonical entry point never calls it. |
|
||||
| `local/scripts/build-redbear.sh` | **Canonical build entry point** for Red Bear profiles | under v6.0 it does NOT call `apply-patches.sh` — the release fork is already in `local/`. It enforces: (1) local-over-WIP recipe priority, (2) overlay integrity verification, (3) dirty-source gate (refuses uncommitted fork edits unless `--allow-dirty`; it does NOT stash the tree), (4) firmware presence warning, (5) profile validation, (6) cookbook build if needed, (7) image build. Canonical reference: `BUILD-SYSTEM.md`. `--upstream` triggers explicit source immutable archived for non-protected recipes. **`--check-sweep` runs `cargo check` against the target triple on every fork + every config recipe BEFORE the cook/prefix cycle, surfacing all type/borrow errors at once.** | does not guarantee every nested upstream source tree is fresh; does not replace explicit subsystem/runtime validation |
|
||||
| `local/scripts/apply-patches.sh` | **Overlay repair** — not a routine build step | under v5.x, applied build-system patches and relinked recipe patch symlinks; under v6.0 this is a no-op for in-tree components (Rule 1 direct edits) and is replaced by `cookbook_apply_patches` for big external projects (Rule 2). See `local/AGENTS.md`. | do not invoke by hand during a normal build. `build-redbear.sh` calls it automatically, and only when `verify-overlay-integrity.sh` fails. |
|
||||
| `local/scripts/build-redbear.sh` | **Canonical build entry point** for Red Bear profiles | under v6.0 it calls `apply-patches.sh` only to auto-repair a failed overlay-integrity check, not as a routine patch-linking step. It enforces: (1) local-over-WIP recipe priority, (2) overlay integrity verification, (3) dirty-source gate (refuses uncommitted fork edits unless `--allow-dirty`; it does NOT stash the tree), (4) firmware presence warning, (5) profile validation, (6) cookbook build if needed, (7) image build. Canonical reference: `BUILD-SYSTEM.md`. `--upstream` triggers an explicit source sync for non-protected recipes. **`--check-sweep` runs `cargo check` against the target triple on every fork + every config recipe BEFORE the cook/prefix cycle, surfacing all type/borrow errors at once.** | does not guarantee every nested upstream source tree is fresh; does not replace explicit subsystem/runtime validation |
|
||||
| `scripts/fetch-all-sources.sh` | Fetch mainline recipe source inputs for builds | downloads mainline/upstream recipe sources, reports status/preflight, and supports config-scoped fetches while leaving local release fork in place | does not mean fetched upstream WIP source is the durable shipping source of truth |
|
||||
| `local/scripts/fetch-sources.sh` | Fetch mainline recipe sources for browsing and patching | when passed `--upstream`, fetches `recipes/*` source trees so the upstream-managed side is locally available for reading, editing, and patch preparation | does not decide whether upstream should replace the local release fork |
|
||||
| `local/scripts/build-redbear-wifictl-redox.sh` | Build `redbear-wifictl` for the Redox target with the repo toolchain | prepends `prefix/x86_64-unknown-redox/sysroot/bin` to `PATH` and runs `cargo build --target x86_64-unknown-redox` in the `redbear-wifictl` crate | does not prove runtime Wi-Fi behavior; only closes the target-build environment gap for this crate |
|
||||
@@ -116,7 +115,7 @@ all failures are listed in a single run.
|
||||
Default Red Bear behavior is local-first:
|
||||
|
||||
- use locally available package/source trees and release fork state for normal builds,
|
||||
- treat upstream immutable archived as an explicit operator action only (`--upstream`, dedicated fetch/sync),
|
||||
- treat an upstream sync as an explicit operator action only (`--upstream`, dedicated fetch/sync),
|
||||
- do not fail policy-level expectations just because upstream network access is temporarily broken.
|
||||
|
||||
This is required so builds and recovery workflows remain operable during upstream outages or
|
||||
@@ -124,7 +123,7 @@ connectivity failures.
|
||||
|
||||
### Upstream sync
|
||||
|
||||
Use `local/scripts/provision-release.sh` when the goal is to immutable archived the top-level upstream Redox base.
|
||||
Use `local/scripts/provision-release.sh` when the goal is to sync the top-level upstream Redox base.
|
||||
|
||||
This is a repository sync operation, not a guarantee that every local subsystem release fork is already
|
||||
rebased cleanly.
|
||||
@@ -150,12 +149,12 @@ This is the core durable-state recovery path, not a normal build step.
|
||||
|
||||
Use `local/scripts/build-redbear.sh` when the goal is to build a tracked Red Bear profile from the
|
||||
current upstream base plus local release fork. Add `--upstream` only when you explicitly want Redox/upstream
|
||||
recipe sources immutable archived during that build.
|
||||
recipe sources synced during that build.
|
||||
|
||||
### Source immutable archived
|
||||
### Source sync
|
||||
|
||||
Use `scripts/fetch-all-sources.sh` and `local/scripts/fetch-sources.sh --upstream` when the goal is to
|
||||
immutable archived recipe source inputs, but do not confuse fetched upstream WIP source with a trusted shipping
|
||||
sync recipe source inputs, but do not confuse fetched upstream WIP source with a trusted shipping
|
||||
source.
|
||||
|
||||
## WIP Rule in Script Terms
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# redbear-notifications — D-Bus Interface
|
||||
|
||||
**Bus:** session
|
||||
**Well-known name:** `org.freedesktop.Notifications`
|
||||
**Object paths:**
|
||||
- `/org/freedesktop/Notifications` — Notifications server
|
||||
|
||||
## Interface: `org.freedesktop.Notifications`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `Notify` | `(app_name: s, replaces_id: u, app_icon: s, summary: s, body: s, actions: as, hints: a{sv}, expire_timeout: i) → (u)` | Create or replace a notification. Returns notification ID. If `replaces_id` is non-zero and matches an existing notification owned by the same sender, the record is updated in-place. Maximum 1024 active notifications. |
|
||||
| `CloseNotification` | `(id: u) → ()` | Close a notification by ID. Emits `NotificationClosed` signal with reason 3 (closed). |
|
||||
| `GetCapabilities` | `() → (as)` | Returns `["body", "body-markup"]` |
|
||||
| `GetServerInformation` | `() → (ssss)` | Returns `("Red Bear Notifications", "redbear", "0.3.1", "1.2")` |
|
||||
| `InvokeAction` | `(id: u, action_key: s) → ()` | Invoke an action on a notification. Validates: (1) caller is the notification owner, (2) the action key was declared at notify time. Emits `ActionInvoked` signal, then removes the notification. |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `Idle` | `b` | Always `false` (idle tracking not implemented) |
|
||||
|
||||
### Signals
|
||||
|
||||
| Signal | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `NotificationClosed` | `(id: u, reason: u)` | A notification was closed. Reason: 1=expired, 2=dismissed, 3=closed. |
|
||||
| `ActionInvoked` | `(id: u, action_key: s)` | An action was invoked on a notification. |
|
||||
|
||||
## Notification Lifecycle
|
||||
|
||||
1. **Creation** (`Notify`): A notification record is stored with owner (sender bus name), action keys, expire timeout, and issue timestamp. Monotonically increasing IDs starting from 1. If `replaces_id` matches an existing record, that record is updated; otherwise a new record is created.
|
||||
|
||||
2. **Expiry** (background sweeper, 500 ms interval): Notifications with `expire_timeout > 0` are checked against `issued_at + expire_timeout`. Expired notifications are removed and `NotificationClosed(1)` is emitted. Notifications with `expire_timeout <= 0` never expire.
|
||||
|
||||
3. **Action invocation** (`InvokeAction`): Validates sender ownership and action key. Emits `ActionInvoked`, then removes the notification and emits `NotificationClosed(2)`.
|
||||
|
||||
4. **Close** (`CloseNotification`): Removes the notification and emits `NotificationClosed(3)`.
|
||||
|
||||
5. **Sender vanishing** (background reaper, 2 s interval): Every 2 seconds, the daemon queries `org.freedesktop.DBus.NameHasOwner` for each tracked sender. If a sender has vanished from the bus, all its notifications are removed and `NotificationClosed(2)` is emitted for each.
|
||||
|
||||
6. **Bound enforcement**: When the active notification count exceeds 1024, the oldest notification (by insertion order) is evicted and `NotificationClosed(2)` is emitted.
|
||||
|
||||
## Action Format
|
||||
|
||||
The `actions` parameter is a flat string array of alternating key-label pairs:
|
||||
```
|
||||
["default", "Open", "reply", "Reply"]
|
||||
```
|
||||
The daemon extracts keys (every even-indexed element) and validates `InvokeAction` against them.
|
||||
|
||||
## Connection
|
||||
|
||||
- Session bus (`ConnectionBuilder::session()`)
|
||||
- Registers well-known name `org.freedesktop.Notifications` on the session bus
|
||||
|
||||
## References
|
||||
- [Desktop Notifications Specification](https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html) v1.2
|
||||
- Conformance: Full Notify/CloseNotification/GetCapabilities/GetServerInformation. Action invocation with ownership validation. Expiry sweeper. Sender reaper for vanished bus names. Bounded notification store (1024 max). No persistence across restarts. No sound/image/hint processing beyond storage. No idle tracking.
|
||||
@@ -0,0 +1,52 @@
|
||||
# redbear-polkit — D-Bus Interface
|
||||
|
||||
**Bus:** system
|
||||
**Well-known name:** `org.freedesktop.PolicyKit1`
|
||||
**Object paths:**
|
||||
- `/org/freedesktop/PolicyKit1/Authority` — Authority object
|
||||
|
||||
## Interface: `org.freedesktop.PolicyKit1.Authority`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `CheckAuthorization` | `(subject_kind: s, subject: a{sv}, action_id: s, details: a{sv}, flags: u, cancellation_id: s) → (b, b, a{sv})` | Check if a subject is authorized for an action. Returns `(authorized, is_challenge, details)`. The subject dictionary must contain `uid` (U32 or I32). UID 0 (root) is always authorized. Other UIDs are checked against the policy file. |
|
||||
| `RegisterAuthenticationAgent` | `(session: (s, o), locale: s, object_path: s) → ()` | No-op stub (authentication agents are not supported) |
|
||||
| `UnregisterAuthenticationAgent` | `(session: (s, o), object_path: s) → ()` | No-op stub |
|
||||
| `EnumerateActions` | `(locale: s) → (a(sssssu(a{sv})))` | Returns empty list (action enumeration not implemented) |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `BackendName` | `s` | `"redbear-uid-policy"` (const) |
|
||||
| `BackendVersion` | `s` | `"0.2.0"` (const) |
|
||||
|
||||
### Authorization Decision Logic
|
||||
|
||||
1. Extract UID from subject dictionary (field `uid`, accepts U32 and I32 types)
|
||||
2. If UID is 0 → authorized (root bypass)
|
||||
3. Look up action ID in the TOML policy file (`/etc/polkit-1/policy.toml` or `REDBEAR_POLKIT_POLICY`)
|
||||
4. Evaluate user specs on the matching line, left to right:
|
||||
- `*` → match any user
|
||||
- `N` (decimal integer) → match specific UID
|
||||
- `@group` → match if UID is a member of the named group
|
||||
- `!spec` → explicit deny
|
||||
5. Explicit deny overrides any explicit allow
|
||||
6. Unknown action → denied by default
|
||||
|
||||
### Subject Format
|
||||
|
||||
The `subject` dictionary is a `HashMap<String, Value>`. Supported fields:
|
||||
- `uid` (u32 or i32): The UID to authorize. Required.
|
||||
|
||||
The `subject_kind` string (e.g. `"unix-user"` or `"unix-process"`) is logged but not used for authorization decisions — only the `uid` field matters.
|
||||
|
||||
### Details Format
|
||||
|
||||
The `details` dictionary (third return value) is always empty. The upstream spec allows backends to return additional key-value pairs; Red Bear's implementation returns an empty `HashMap`.
|
||||
|
||||
## References
|
||||
- [PolicyKit D-Bus API](https://www.freedesktop.org/software/polkit/docs/latest/ref-dbus-api.html)
|
||||
- Conformance: Minimal implementation. `CheckAuthorization` with UID-based policy file evaluation. No authentication agent support (Register/Unregister are no-ops). No action enumeration. No JavaScript rules.d support. Backend is a simple TOML key-value store.
|
||||
@@ -0,0 +1,152 @@
|
||||
# redbear-sessiond — D-Bus Interface
|
||||
|
||||
**Bus:** system
|
||||
**Well-known name:** `org.freedesktop.login1`
|
||||
**Object paths:**
|
||||
- `/org/freedesktop/login1` — Manager object (main entry point)
|
||||
- `/org/freedesktop/login1/session/c1` — Session object
|
||||
- `/org/freedesktop/login1/seat/seat0` — Seat object
|
||||
- `/org/freedesktop/login1/user/current` — User object
|
||||
|
||||
## Interface: `org.freedesktop.login1.Manager`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `GetSession` | `(id: s) → (o)` | Returns object path for session by ID |
|
||||
| `GetSessionByPID` | `(pid: u) → (o)` | Returns object path for session owning PID (stub: returns c1) |
|
||||
| `ListSessions` | `() → (a(susso))` | List all sessions: `[(id, uid, user, seat, object_path)]` |
|
||||
| `GetSeat` | `(id: s) → (o)` | Returns object path for seat by ID |
|
||||
| `ListSeats` | `() → (a(so))` | List all seats: `[(id, object_path)]` |
|
||||
| `GetUser` | `(uid: u) → (o)` | Returns object path for user by UID |
|
||||
| `GetUserByPID` | `(pid: u) → (o)` | Returns object path for user owning PID (stub: returns current) |
|
||||
| `ListUsers` | `() → (a(uso))` | List all users: `[(uid, name, object_path)]` |
|
||||
| `ListInhibitors` | `() → (a(ssssuu))` | List all registered inhibitors |
|
||||
| `Inhibit` | `(what: s, who: s, why: s, mode: s) → (h)` | Register a shutdown/sleep inhibitor; returns pipe FD. The inhibitor is tracked by sender bus name; removal occurs on FD close or sender vanishing |
|
||||
| `PowerOff` | `(interactive: b) → ()` | Shut down the system. Writes `\n` to `/scheme/acpi/shutdown`. Emits `PrepareForShutdown(true)` before and `PrepareForShutdown(false)` after. |
|
||||
| `Reboot` | `(interactive: b) → ()` | Reboot the system. Writes `\n` to `/scheme/acpi/reboot`. Emits `PrepareForShutdown(true)` before. |
|
||||
| `Suspend` | `(interactive: b) → ()` | Suspend the system. Emits `PrepareForSleep(true)` before and `PrepareForSleep(false)` after. |
|
||||
| `CanPowerOff` | `() → (s)` | Returns `"yes"`, `"no"`, or `"challenge"` (always `"yes"` when `/scheme/acpi/shutdown` is writable) |
|
||||
| `CanReboot` | `() → (s)` | Returns `"yes"`, `"no"`, or `"challenge"` |
|
||||
| `CanSuspend` | `() → (s)` | Returns `"yes"`, `"no"`, or `"challenge"` (stub: always `"no"`) |
|
||||
| `CanHibernate` | `() → (s)` | Stub: always `"no"` |
|
||||
| `CanHybridSleep` | `() → (s)` | Stub: always `"no"` |
|
||||
| `CanSuspendThenHibernate` | `() → (s)` | Stub: always `"no"` |
|
||||
| `CanSleep` | `() → (s)` | Aggregate: `"yes"` if any sleep state is available |
|
||||
| `ActivateSession` | `(session_id: s) → ()` | Mark session as active |
|
||||
| `ActivateSessionOnSeat` | `(session_id: s, seat_id: s) → ()` | Activate session on specific seat |
|
||||
| `LockSession` | `(session_id: s) → ()` | Lock a specific session |
|
||||
| `UnlockSession` | `(session_id: s) → ()` | Unlock a specific session |
|
||||
| `LockSessions` | `() → ()` | Lock all sessions |
|
||||
| `UnlockSessions` | `() → ()` | Unlock all sessions |
|
||||
| `TerminateSession` | `(session_id: s) → ()` | Terminate a specific session |
|
||||
| `TerminateUser` | `(uid: u) → ()` | Terminate all sessions for a user |
|
||||
| `KillSession` | `(session_id: s, who: s, signal_number: i) → ()` | Send signal to session leader |
|
||||
| `KillUser` | `(uid: u, signal_number: i) → ()` | Send signal to user session leader |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `IdleHint` | `b` | Whether the seat has been idle for the configured timeout |
|
||||
| `IdleSinceHint` | `t` | CLOCK_REALTIME timestamp of last activity |
|
||||
| `IdleSinceHintMonotonic` | `t` | CLOCK_MONOTONIC timestamp of last activity |
|
||||
| `BlockInhibited` | `s` | Colon-separated list of `who:why` for block-mode inhibitors |
|
||||
| `DelayInhibited` | `s` | Colon-separated list of `who:why` for delay-mode inhibitors |
|
||||
| `InhibitDelayMaxUSec` | `t` | Maximum delay before forced shutdown (5 s default) |
|
||||
| `HandleLidSwitch` | `s` | Lid switch policy: `"ignore"` (default) |
|
||||
| `HandlePowerKey` | `s` | Power key policy: `"poweroff"` (default) |
|
||||
| `PreparingForShutdown` | `b` | Whether a shutdown operation is in progress |
|
||||
| `PreparingForSleep` | `b` | Whether a sleep operation is in progress |
|
||||
|
||||
### Signals
|
||||
|
||||
| Signal | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `SeatNew` | `(id: s, path: o)` | A new seat was added |
|
||||
| `SeatRemoved` | `(id: s, path: o)` | A seat was removed |
|
||||
| `PrepareForShutdown` | `(active: b)` | Shutdown is about to begin / has completed |
|
||||
| `PrepareForSleep` | `(active: b)` | Sleep is about to begin / has completed |
|
||||
|
||||
## Interface: `org.freedesktop.login1.Session`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `Activate` | `() → ()` | Activate this session |
|
||||
| `TakeControl` | `(force: b) → ()` | Take control of the session |
|
||||
| `ReleaseControl` | `() → ()` | Release session control |
|
||||
| `TakeDevice` | `(major: u, minor: u) → (h)` | Take a device (returns FD). Emits `PauseDevice` signal. |
|
||||
| `ReleaseDevice` | `(major: u, minor: u) → ()` | Release a previously-taken device. Emits `ResumeDevice` signal. |
|
||||
| `PauseDeviceComplete` | `(major: u, minor: u) → ()` | Signal that device pause is complete |
|
||||
| `SetIdleHint` | `(idle: b) → ()` | Set the session idle state |
|
||||
| `SetLockedHint` | `(locked: b) → ()` | Set the session lock state |
|
||||
| `SetType` | `(type: s) → ()` | Set the session type (e.g. `"wayland"`) |
|
||||
| `Terminate` | `() → ()` | Terminate this session |
|
||||
| `Kill` | `(who: s, signal_number: i) → ()` | Send signal to session process |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `Active` | `b` | Whether this session is currently active |
|
||||
| `Remote` | `b` | Whether this is a remote session (always false) |
|
||||
|
||||
### Signals
|
||||
|
||||
| Signal | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `PauseDevice` | `(major: u, minor: u, type: s)` | A device is being paused |
|
||||
| `ResumeDevice` | `(major: u, minor: u, fd: h)` | A device is being resumed (FD re-opened) |
|
||||
|
||||
## Interface: `org.freedesktop.login1.Seat`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `SwitchTo` | `(vt: u) → ()` | Switch to virtual terminal |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `Id` | `s` | Seat identifier (default: `"seat0"`) |
|
||||
| `ActiveSession` | `(s, o)` | Active session ID and object path |
|
||||
| `Sessions` | `a(so)` | List of sessions on this seat |
|
||||
| `CanGraphical` | `b` | Whether this seat supports graphical sessions (always `true`) |
|
||||
| `CanTTY` | `b` | Whether this seat supports TTY sessions (always `true`) |
|
||||
| `IdleHint` | `b` | Whether this seat is idle |
|
||||
|
||||
## Runtime State
|
||||
|
||||
The daemon maintains a `SharedRuntime` (RwLock-protected) with:
|
||||
- `seat_id`: current seat identifier
|
||||
- `session_id`: current session identifier
|
||||
- `uid`: current user UID
|
||||
- `user_name`: current user name
|
||||
- `display`: current display number
|
||||
- `vt`: current virtual terminal
|
||||
- `session_type`: session type string
|
||||
- `inhibitors`: list of registered inhibitors with sender tracking
|
||||
- `last_activity`: monotonic timestamp
|
||||
|
||||
## AC adapter / power events
|
||||
|
||||
The `acpi_watcher` background task:
|
||||
- Reads `/sys/class/power_supply/ACAD/online` every 2 s (or `/sys/class/power_supply/AC*/online`)
|
||||
- Emits `PropertyChanged` on `org.freedesktop.login1.Manager` when the AC state transitions
|
||||
- Transitions are debounced: an event is only emitted when the state actually changes
|
||||
|
||||
## Connection
|
||||
|
||||
- Uses zbus `ConnectionBuilder` with the system bus address from `DBUS_STARTER_ADDRESS` or `DBUS_SYSTEM_BUS_ADDRESS` (default: `unix:path=/run/dbus/system_bus_socket`)
|
||||
- Waits up to 30 s for the D-Bus socket, polling multiple candidate paths
|
||||
- Retries connection 3 times with 1 s backoff (first attempt failure is silent — normal when D-Bus SASL auth is not yet ready)
|
||||
- Exposes a UNIX control socket at `/run/redbear-sessiond/control` for out-of-band commands (e.g. `reload`)
|
||||
|
||||
## References
|
||||
- [systemd-logind D-Bus API](https://www.freedesktop.org/wiki/Software/systemd/logind/)
|
||||
- Conformance: Subset-compatible. Implements the login1 Manager, Session, and Seat interfaces. Inhibitor tracking with FD-polling reaper. Power/sleep operations via ACPI scheme. No user session tracking beyond a single "current" user. No multi-seat support. Device take/release with PauseDevice/ResumeDevice signal contract.
|
||||
@@ -0,0 +1,67 @@
|
||||
# redbear-statusnotifierwatcher — D-Bus Interface
|
||||
|
||||
**Bus:** session
|
||||
**Well-known name:** `org.kde.StatusNotifierWatcher`
|
||||
**Object paths:**
|
||||
- `/StatusNotifierWatcher` — Watcher object
|
||||
|
||||
## Interface: `org.kde.StatusNotifierWatcher`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `RegisterStatusNotifierItem` | `(item: s) → ()` | Register a status notifier item. The `item` parameter is either a full object path (e.g. `/org/example/Item`) or a bus name (e.g. `:1.42` or `org.example.App`). Object paths from different senders are deduplicated by prepending the sender's unique bus name. Emits `StatusNotifierItemRegistered`. |
|
||||
| `UnregisterStatusNotifierItem` | `(item: s) → ()` | Unregister a previously-registered item. Only the original owning sender can unregister. Emits `StatusNotifierItemUnregistered`. |
|
||||
| `RegisterStatusNotifierHost` | `(host: s) → ()` | Register a status notifier host (typically the system tray panel). Emits `StatusNotifierHostRegistered`. |
|
||||
| `UnregisterStatusNotifierHost` | `(host: s) → ()` | Unregister a status notifier host. Only the original owning sender can unregister. |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `RegisteredStatusNotifierItems` | `as` | Read-only list of registered item bus names/paths |
|
||||
| `IsStatusNotifierHostRegistered` | `b` | Read-only: true if at least one host is registered |
|
||||
| `ProtocolVersion` | `i` | Always `0` (per KDE spec) |
|
||||
|
||||
### Signals
|
||||
|
||||
| Signal | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `StatusNotifierItemRegistered` | `(service: s)` | A new status notifier item was registered |
|
||||
| `StatusNotifierItemUnregistered` | `(service: s)` | A status notifier item was unregistered |
|
||||
| `StatusNotifierHostRegistered` | `() → ()` | A new status notifier host was registered |
|
||||
| `StatusNotifierHostUnregistered` | `() → ()` | A status notifier host was unregistered |
|
||||
|
||||
## Ownership and Deduplication
|
||||
|
||||
- Each registration is owned by the caller's unique bus name (from the D-Bus message header).
|
||||
- Object paths (values starting with `/`) are namespaced by sender: `:1.42/StatusNotifierItem` is distinct from `:1.99/StatusNotifierItem`. The display value (via `RegisteredStatusNotifierItems` property and signals) strips the owner prefix.
|
||||
- Bus names (values not starting with `/`) are treated as-is — the first registration wins.
|
||||
- Only the owning sender can unregister its own entries. Calling `Unregister` with the wrong sender is a silent no-op.
|
||||
- Maximum 1024 entries per registry (items and hosts independently bounded). Oldest-first eviction when full.
|
||||
|
||||
## NameOwnerChanged Listener
|
||||
|
||||
A background task subscribes to `org.freedesktop.DBus.NameOwnerChanged` signals on the session bus. When a unique bus name (starting with `:`) releases its bus name (new owner is empty), all items and hosts owned by that sender are purged and the appropriate unregistration signals are emitted.
|
||||
|
||||
Well-known name releases (e.g. `org.example.App` losing its bus name) do NOT trigger automatic purge — only unique name (`:1.N`) releases do. This matches KDE spec behavior.
|
||||
|
||||
## Input Validation
|
||||
|
||||
All registration values are validated:
|
||||
- Must be non-empty
|
||||
- Maximum length 256 characters
|
||||
- Must not contain NUL or other control characters (including C0/C1 control codes and Unicode format chars)
|
||||
- Invalid values are rejected with `org.freedesktop.DBus.Error.InvalidArgs`
|
||||
|
||||
## Connection
|
||||
|
||||
- Session bus (`ConnectionBuilder::session()`)
|
||||
- Waits up to 6 s for `DBUS_SESSION_BUS_ADDRESS` env var to be set (30 polls at 200 ms)
|
||||
- Registers well-known name on session bus
|
||||
- SIGTERM/Ctrl-C handler for clean shutdown
|
||||
|
||||
## References
|
||||
- [KDE StatusNotifierItem Specification](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/)
|
||||
- Conformance: Full StatusNotifierWatcher implementation. Owner-keyed item/host tracking with canonical deduplication. NameOwnerChanged-based auto-purge for vanished unique bus names. Bounded registries with deterministic eviction. Input validation. All four registration/unregistration methods, three properties, and all four signals.
|
||||
@@ -0,0 +1,103 @@
|
||||
# redbear-udisks — D-Bus Interface
|
||||
|
||||
**Bus:** system
|
||||
**Well-known name:** `org.freedesktop.UDisks2`
|
||||
**Object paths:**
|
||||
- `/org/freedesktop/UDisks2` — ObjectManager root
|
||||
- `/org/freedesktop/UDisks2/Manager` — Manager object
|
||||
- `/org/freedesktop/UDisks2/drives/<id>` — Per-drive objects
|
||||
- `/org/freedesktop/UDisks2/block_devices/<id>` — Per-block objects
|
||||
|
||||
## Interface: `org.freedesktop.DBus.ObjectManager`
|
||||
|
||||
At `/org/freedesktop/UDisks2`:
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `GetManagedObjects` | `() → (a{oa{sa{sv}}})` | Return all managed objects with their interfaces and properties |
|
||||
|
||||
| Signal | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `InterfacesAdded` | `(o, a{sa{sv}})` | New interfaces appeared on an object path |
|
||||
| `InterfacesRemoved` | `(o, as)` | Interfaces were removed from an object path |
|
||||
|
||||
## Interface: `org.freedesktop.UDisks2.Manager`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `GetBlockDevices` | `(options: a{sv}) → (ao)` | List all block device object paths |
|
||||
| `GetDrives` | `(options: a{sv}) → (ao)` | List all drive object paths |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `Version` | `s` | Package version (from `CARGO_PKG_VERSION`) |
|
||||
| `SupportedFilesystems` | `as` | Currently empty (filesystem support detects at mount time) |
|
||||
| `SupportedEncryptionTypes` | `as` | Empty (encryption not supported) |
|
||||
| `DefaultEncryptionType` | `s` | Empty |
|
||||
|
||||
## Interface: `org.freedesktop.UDisks2.Drive`
|
||||
|
||||
### Methods
|
||||
|
||||
None (property-only interface).
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `ConnectionBus` | `s` | Scheme identity string (e.g. `"scheme:ahci"`, `"scheme:nvme"`) |
|
||||
| `Size` | `t` | Total drive size in bytes |
|
||||
|
||||
## Interface: `org.freedesktop.UDisks2.Block`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `Mount` | `(options: a{sv}) → (s)` | Mount the block device. Accepts `fstype` option (`"ext4"` or `"vfat"`). Auto-detects ext4 (magic 0xEF53 at offset 0x438) and FAT (magic 0x4D44 at end of VBR). Returns mount point path. |
|
||||
| `Unmount` | `(options: a{sv}) → ()` | Unmount a previously-mounted block device. Sends SIGTERM to the child filesystem daemon. |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `Device` | `ay` | Device path as byte array |
|
||||
| `PreferredDevice` | `ay` | Preferred device path (same as Device) |
|
||||
| `Symlinks` | `aay` | Empty (no symlink tracking) |
|
||||
| `Size` | `t` | Block device size in bytes |
|
||||
| `ReadOnly` | `b` | Whether the device is read-only |
|
||||
| `Drive` | `o` | Parent drive object path |
|
||||
| `HintPartitionable` | `b` | Whether the block is a partitionable device |
|
||||
| `MountPoints` | `aay` | Current mount points (empty when not mounted) |
|
||||
| `IdType` | `s` | Detected filesystem type: `"ext4"`, `"vfat"`, or `""` (unknown) |
|
||||
|
||||
## Inventory Discovery
|
||||
|
||||
At startup, `Inventory::scan()` enumerates block devices from:
|
||||
- `/scheme/diskd/` — disk aggregator scheme (BlockDev entries)
|
||||
- `/scheme/ahci/` — AHCI scheme
|
||||
- `/scheme/nvme/` — NVMe scheme
|
||||
|
||||
Each device is classified as a `DriveDevice` with associated `BlockDevice` entries. Object paths are stable (derived from the device name).
|
||||
|
||||
## Filesystem Detection
|
||||
|
||||
`detect_filesystem(device_path)` reads the block device:
|
||||
1. Offset 0x438: ext4 magic (`0xEF53` at bytes 56-57 of superblock)
|
||||
2. End of VBR: FAT magic (`0x4D44` signature at VBR tail)
|
||||
|
||||
If `fstype` is passed as a mount option, it takes precedence over detection.
|
||||
|
||||
## Connection
|
||||
|
||||
- System bus, same `DBUS_STARTER_ADDRESS` / `DBUS_SYSTEM_BUS_ADDRESS` env var resolution as other D-Bus daemons
|
||||
- 3 retry attempts at 1 s intervals
|
||||
- SIGTERM/Ctrl-C handler for clean shutdown
|
||||
|
||||
## References
|
||||
- [UDisks2 D-Bus API](https://udisks.freedesktop.org/docs/latest/ref-dbus.html)
|
||||
- Conformance: Subset implementation. Drive and Block objects with static properties. Mount/Unmount with ext4 and FAT support. ObjectManager for discovery. No ATA, partition table, filesystem size, or SMART interfaces. No encryption, RAID, or loop support.
|
||||
@@ -0,0 +1,111 @@
|
||||
# redbear-upower — D-Bus Interface
|
||||
|
||||
**Bus:** system
|
||||
**Well-known name:** `org.freedesktop.UPower`
|
||||
**Object paths:**
|
||||
- `/org/freedesktop/UPower` — UPower daemon root
|
||||
- `/org/freedesktop/UPower/devices/DisplayDevice` — Composite display device
|
||||
- `/org/freedesktop/UPower/devices/line_power_<id>` — Per-adapter AC power devices
|
||||
- `/org/freedesktop/UPower/devices/battery_<id>` — Per-battery devices
|
||||
|
||||
## Interface: `org.freedesktop.UPower`
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `EnumerateDevices` | `() → (ao)` | List all device object paths |
|
||||
| `GetCriticalAction` | `() → (s)` | Returns `"PowerOff"` |
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `DaemonVersion` | `s` | `"0.1.0"` (const) |
|
||||
| `OnBattery` | `b` | Whether running on battery (no AC adapters online and at least one battery discharging). Computed from snapshot. |
|
||||
|
||||
### Signals
|
||||
|
||||
| Signal | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `Changed` | `()` | Power state changed (emitted on poll interval or ACPI notification) |
|
||||
|
||||
## Interface: `org.freedesktop.UPower.Device`
|
||||
|
||||
### Methods
|
||||
|
||||
None (property-only interface).
|
||||
|
||||
### Properties (all devices)
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `Type` | `u` | Device kind: 0=unknown, 1=line power, 2=battery |
|
||||
| `State` | `u` | Device state: 0=unknown, 1=charging, 2=discharging, 3=empty, 4=fully charged |
|
||||
| `Percentage` | `d` | Battery percentage (0.0–100.0). 0.0 for adapters, average across batteries for DisplayDevice |
|
||||
| `IsPresent` | `b` | Whether the device hardware is present |
|
||||
| `Online` | `b` | True for AC adapters that are plugged in; false for batteries |
|
||||
| `NativePath` | `s` | ACPI scheme path (e.g. `/scheme/acpi/power/adapters/ACAD`) |
|
||||
| `TimeToFull` | `x` | Seconds until fully charged (0 if not charging) |
|
||||
| `TimeToEmpty` | `x` | Seconds until empty (0 if not discharging) |
|
||||
| `Energy` | `d` | Current energy in Wh |
|
||||
| `EnergyRate` | `d` | Present power draw in W (positive=discharging, negative=charging) |
|
||||
| `BatteryLevel` | `u` | Higher-level battery status: 0=unknown, 3=normal, 4=low, 5=critical, 7=full |
|
||||
| `PowerSupply` | `b` | Whether the device supplies power (true for online adapters, false for batteries) |
|
||||
| `Serial` | `s` | Hardware serial identifier |
|
||||
|
||||
### DisplayDevice properties
|
||||
|
||||
The DisplayDevice at `/org/freedesktop/UPower/devices/DisplayDevice` is a composite view:
|
||||
- `Type`: `DEVICE_KIND_BATTERY` if at least one battery exists, else `DEVICE_KIND_UNKNOWN`
|
||||
- `State`: Aggregate state across all batteries (charging if any battery charging, discharging if any battery discharging)
|
||||
- `Percentage`: Average of all battery percentages
|
||||
- `IsPresent`: True if at least one battery exists
|
||||
- `Online`: Always false
|
||||
|
||||
## State Discovery
|
||||
|
||||
At startup, `PowerRuntime::discover()` reads:
|
||||
- `/scheme/acpi/power/adapters/` — lists subdirectories, each an AC adapter
|
||||
- `/scheme/acpi/power/batteries/` — lists subdirectories, each a battery
|
||||
|
||||
For each adapter:
|
||||
- `path` — native ACPI path
|
||||
- `online` — `u64`, non-zero means plugged in
|
||||
|
||||
For each battery:
|
||||
- `path` — native ACPI path
|
||||
- `state` — `u64` bitmask (bit 0=discharging, bit 1=charging, bit 2=critical)
|
||||
- `percentage` — `f64`, percentage charge
|
||||
- `energy` — `f64`, energy in Wh
|
||||
- `energy_rate` — `f64`, power in W
|
||||
- `time_to_full` — `f64`, seconds
|
||||
- `time_to_empty` — `f64`, seconds
|
||||
- `serial` — hardware serial string
|
||||
|
||||
## State Change Detection
|
||||
|
||||
Two mechanisms:
|
||||
1. **Poll interval:** Every 30 seconds (`POLL_INTERVAL_SECS`), take a snapshot and compare with the last. If the state changed, emit `Changed` signal.
|
||||
2. **ACPI notification drain:** Every 250 ms (`NOTIFICATION_POLL_MS`), read `/scheme/acpi/notifications`. If notifications are present and the state changed, emit `Changed` signal. This reduces battery state change latency from 30 s to sub-second for ACPI-aware hardware.
|
||||
|
||||
## Battery Level Mapping
|
||||
|
||||
| Condition | Level |
|
||||
|-----------|-------|
|
||||
| State bit 0x4 (critical) set | `BATTERY_LEVEL_CRITICAL` (5) |
|
||||
| Percentage < 10.0 | `BATTERY_LEVEL_CRITICAL` (5) |
|
||||
| 10.0 ≤ Percentage < 25.0 | `BATTERY_LEVEL_LOW` (4) |
|
||||
| Percentage ≥ 100.0 | `BATTERY_LEVEL_FULL` (7) |
|
||||
| 25.0 ≤ Percentage < 100.0 | `BATTERY_LEVEL_NORMAL` (3) |
|
||||
| Percentage unavailable | `BATTERY_LEVEL_UNKNOWN` (0) |
|
||||
|
||||
## Connection
|
||||
|
||||
- System bus, same env var resolution as other D-Bus daemons
|
||||
- 3 retry attempts at 1 s intervals
|
||||
- If `/scheme/acpi/power` is unavailable, serves an empty provisional UPower surface (no devices, daemon still registers on bus)
|
||||
|
||||
## References
|
||||
- [UPower D-Bus API](https://upower.freedesktop.org/docs/ref-dbus.html)
|
||||
- Conformance: Subset implementation. Device enumeration from ACPI power scheme. Composite DisplayDevice. Changed signal on state transitions. No history/statistics. No Wakeups API. No suspend/hibernate integration (handled by login1). No backlight control.
|
||||
@@ -0,0 +1,50 @@
|
||||
# redbear-accessibility — Operator Runbook
|
||||
|
||||
**Daemon:** redbear-accessibility
|
||||
**Init service:** `/usr/lib/init.d/60_accessibility.service`
|
||||
**Status check:** `cat /scheme/accessibility/status`
|
||||
**Restart:** `init-svc restart accessibility`
|
||||
|
||||
## Logs
|
||||
- Destination: `stderr` (tagged `[accessibility]`)
|
||||
- No env-var log level control; all messages are `INFO` or `ERROR` level. To increase verbosity, modify `src/main.rs:log_msg` calls.
|
||||
|
||||
## Scheme
|
||||
- **Scheme name:** `accessibility`
|
||||
- **Root:** `/scheme/accessibility/` (directory, mode 0555)
|
||||
|
||||
## Scheme Paths
|
||||
| Path | Type | Mode | Description |
|
||||
|------|------|------|-------------|
|
||||
| `config` | file | 0644 | Read/write accessibility config (`key=value` lines) |
|
||||
| `status` | file | 0644 | Read-only runtime status summary |
|
||||
| `sticky-keys` | file | 0644 | Read active sticky modifiers; write `key <code> <pressed> [now_ms]` to feed input |
|
||||
|
||||
## Config Properties (read/write via `config`)
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `sticky_keys` | bool | false | Enable sticky key modifier latching |
|
||||
| `slow_keys` | bool | false | Enforce minimum key press duration |
|
||||
| `slow_key_delay_ms` | u64 | 300 | Minimum press duration for slow keys |
|
||||
| `bounce_keys` | bool | false | Debounce rapid double-presses |
|
||||
| `bounce_key_delay_ms` | u64 | 300 | Minimum interval between presses |
|
||||
| `repeat_keys` | bool | true | Enable key repeat |
|
||||
| `repeat_delay_ms` | u64 | 500 | Delay before repeat starts |
|
||||
|
||||
## Sticky Key Modifier Scan Codes
|
||||
| Code | Modifier |
|
||||
|------|----------|
|
||||
| 0x1D, 0x61, 0x64 | Ctrl |
|
||||
| 0x2A, 0x36 | Shift |
|
||||
| 0x38 | Alt |
|
||||
| 0x5B, 0x5C | Meta (Super) |
|
||||
|
||||
## Signals / SIGTERM Behavior
|
||||
- No SIGTERM handler. Scheme socket close triggers clean exit. Registered via `register_sync_scheme`.
|
||||
|
||||
## Common Issues
|
||||
1. **`failed to register scheme:accessibility`** — Another daemon already registered the scheme name, or the scheme socket could not be created. Check for duplicate instances.
|
||||
2. **Sticky keys not working** — Verify `sticky_keys=true` in config (`cat /scheme/accessibility/config`). The daemon must receive key events via `write` to `sticky-keys` (format: `key <scancode> <pressed_bool> [now_ms]`). Passive — not auto-fed by the input stack yet.
|
||||
3. **Bounce/slow key filtering too aggressive** — Adjust `slow_key_delay_ms` and `bounce_key_delay_ms` via config write. Increase values for users with tremors, decrease for fast typists.
|
||||
4. **Config changes not persisting** — Config is in-memory only. No persistence to disk. Re-apply config via init service `[[files]]` entries or a startup script that writes to `/scheme/accessibility/config`.
|
||||
5. **Root listing returns empty** — The root directory listing is hardcoded (`config\nstatus\nsticky-keys\n`). If `getdents` returns unexpected results, check that the caller uses correct Redox scheme I/O conventions.
|
||||
@@ -0,0 +1,53 @@
|
||||
# redbear-btctl — Operator Runbook
|
||||
|
||||
**Daemon:** redbear-btctl
|
||||
**Init service:** `/usr/lib/init.d/21_btctl.service`
|
||||
**Status check:** `redbear-btctl --status [adapter]`
|
||||
**Restart:** `init-svc restart btctl`
|
||||
|
||||
## Logs
|
||||
- Destination: `stderr` (visible via `journalctl -u btctl`)
|
||||
- Debug: `REDBEAR_BTCTL_LOG=debug redbear-btctl [command]`
|
||||
- Trace: `REDBEAR_BTCTL_LOG=trace redbear-btctl [command]`
|
||||
|
||||
## Modes
|
||||
- CLI commands (one-shot): `--probe`, `--status`, `--scan`, `--bond-list`, `--bond-add-stub`, `--bond-remove`, `--connect`, `--disconnect`, `--read-char`
|
||||
- Daemon mode (no args, Redox only): Long-running `scheme:btctl` daemon. Handles connect/disconnect/read-char via scheme write paths. On Redox host, CLI commands (`--connect`, `--disconnect`, `--read-char`) forward requests to the live daemon via `scheme:btctl` paths.
|
||||
|
||||
## CLI Commands
|
||||
| Command | Usage | Description |
|
||||
|---------|-------|-------------|
|
||||
| `--probe` | `redbear-btctl --probe` | Adapter list + capabilities |
|
||||
| `--status` | `redbear-btctl --status [hciN]` | Adapter status, bond count, scan result count |
|
||||
| `--scan` | `redbear-btctl --scan [hciN]` | Trigger stub scan (returns `demo-beacon,demo-sensor`) |
|
||||
| `--bond-list` | `redbear-btctl --bond-list [hciN]` | List persisted bond records |
|
||||
| `--bond-add-stub` | `redbear-btctl --bond-add-stub hci0 AA:BB:CC:DD:EE:FF [alias]` | Add stub bond record |
|
||||
| `--bond-remove` | `redbear-btctl --bond-remove hci0 AA:BB:CC:DD:EE:FF` | Remove bond record |
|
||||
| `--connect` | `redbear-btctl --connect hci0 AA:BB:CC:DD:EE:FF` | Connect to bonded device |
|
||||
| `--disconnect` | `redbear-btctl --disconnect hci0 AA:BB:CC:DD:EE:FF` | Disconnect bonded device |
|
||||
| `--read-char` | `redbear-btctl --read-char hci0 AA:BB:CC:DD:EE:FF <svc-uuid> <char-uuid>` | Read GATT characteristic |
|
||||
|
||||
## Backend Selection
|
||||
- `REDBEAR_BTCTL_BACKEND=stub` (default) — Stub backend with hardcoded adapter `hci0`
|
||||
- `REDBEAR_BTCTL_BACKEND=hci` — Live HCI backend (reads from /scheme/btusb)
|
||||
|
||||
## Scheme Paths (Daemon Mode, Redox Only)
|
||||
- `/scheme/btctl/adapters/<adapter>/status` — Connection status
|
||||
- `/scheme/btctl/adapters/<adapter>/transport-status` — Transport health
|
||||
- `/scheme/btctl/adapters/<adapter>/connection-state` — Connected bond IDs
|
||||
- `/scheme/btctl/adapters/<adapter>/connect` — Write bond ID to connect
|
||||
- `/scheme/btctl/adapters/<adapter>/disconnect` — Write bond ID to disconnect
|
||||
- `/scheme/btctl/adapters/<adapter>/read-char` — Write bond/service/char UUIDs to read
|
||||
- `/scheme/btctl/adapters/<adapter>/connect-result` — Last connect result
|
||||
- `/scheme/btctl/adapters/<adapter>/disconnect-result` — Last disconnect result
|
||||
- `/scheme/btctl/adapters/<adapter>/read-char-result` — Last read-char result
|
||||
|
||||
## Signals / SIGTERM Behavior
|
||||
- No SIGTERM handler; killed by init system. Daemon uses `INIT_NOTIFY` fd for scheme-ready notification.
|
||||
|
||||
## Common Issues
|
||||
1. **`redbear-btctl daemon is not serving scheme:btctl`** — CLI command attempted a scheme write on a host without the daemon running. Start the daemon first (`redbear-btctl` with no args on Redox), or use the stub CLI path on the host (connect/disconnect/read-char output is marked `runtime_scope=process-local-host-cli`).
|
||||
2. **`bond record not found`** — Bond must be created via `--bond-add-stub` before `--connect`/`--disconnect`/`--read-char`. Bonds persist to `bond_store_root` on disk.
|
||||
3. **`explicit-startup-required` in status** — Transport runtime (`redbear-btusb --daemon`) is not running or its status file is missing/stale. The control daemon requires the USB transport layer to be active.
|
||||
4. **`only the experimental` error on `--read-char`** — The stub backend only supports reading the Battery Service (0x180F) Battery Level (0x2A19) characteristic. Other UUIDs are rejected with this message.
|
||||
5. **Stub backend limitation** — All commands produce bounded stub responses suitable for development/testing. Real hardware requires `REDBEAR_BTCTL_BACKEND=hci` with a live `redbear-btusb` daemon serving the USB transport.
|
||||
@@ -0,0 +1,34 @@
|
||||
# redbear-btusb — Operator Runbook
|
||||
|
||||
**Daemon:** redbear-btusb
|
||||
**Init service:** `/usr/lib/init.d/20_btusb.service`
|
||||
**Status check:** `redbear-btusb --status`
|
||||
**Restart:** `init-svc restart btusb`
|
||||
|
||||
## Logs
|
||||
- Destination: `stderr` (visible via `journalctl -u btusb`)
|
||||
- Debug: `RUST_LOG=debug redbear-btusb --daemon`
|
||||
- Trace: `RUST_LOG=trace redbear-btusb --daemon`
|
||||
|
||||
## Modes
|
||||
- `redbear-btusb --probe` — One-shot USB bus scan for Bluetooth adapters. Prints `adapters=`, `transport=usb`, `mode=ble-first`, adapter endpoint detail lines.
|
||||
- `redbear-btusb --status` — Reads `/var/run/redbear-btusb/status` (90 s freshness window). Prints `runtime_visibility`, `daemon_status`, `controller_state`, `bd_address`, `hci_version`.
|
||||
- `redbear-btusb --daemon` (default, no args) — Long-running daemon. Scans `/scheme/usb/` for Bluetooth adapters (USB class 0xE0, subclass 0x01; known-vendor fallback for Intel 0x8087, Realtek 0x0BDA, Broadcom 0x0A5C, CSR 0x0A12). Runs HCI init sequence (Reset → Read BD Addr → Read Local Version) on first adapter. Registers `scheme:btusb` via `redox_scheme::Socket`.
|
||||
|
||||
## Runtime State Query
|
||||
- Adapter enumeration: `cat /scheme/btusb/adapters` (or read from probe output)
|
||||
- Controller info: `cat /var/run/redbear-btusb/status`
|
||||
- `controller_state` = `closed | initializing | active | error`
|
||||
- `bd_address`, `hci_version`, `hci_revision`, `manufacturer`
|
||||
- `init_error` (present when state is `error`)
|
||||
- USB probe raw: `redbear-btusb --probe` (parses `/scheme/usb` tree)
|
||||
|
||||
## Signals / SIGTERM Behavior
|
||||
- No SIGTERM handler. The init system kills the process directly. The status file at `/var/run/redbear-btusb/status` is cleaned up on normal exit via `Drop`.
|
||||
|
||||
## Common Issues
|
||||
1. **No adapters found** — Verify USB controller is up (`ls /scheme/usb`). Check USB descriptors exist at `/scheme/usb/<bus>/<port>/descriptors`. The daemon probes only USB class 0xE0 subclass 0x01 devices, plus known-vendor fallback (vendor IDs 0x8087, 0x0BDA, 0x0A5C, 0x0A12). Non-Bluetooth-class devices from unknown vendors are invisible.
|
||||
2. **`controller_state=error` with `init_error`** — HCI init sequence failed. Common causes: USB transport is closed, HCI Reset timed out (no event endpoint interrupt), malformed endpoint descriptors (missing interrupt IN, bulk IN, or bulk OUT).
|
||||
3. **Intel CNVi (0x8087) init failure** — Intel firmware setup (`btintel::intel_setup_firmware`) is non-fatal. The `log::warn!` message means standard HCI init will still be attempted. Check `/var/run/redbear-btusb/status` for the resulting controller state.
|
||||
4. **Stale status file** — Status files older than 90 seconds (`STATUS_FRESHNESS_SECS`) are treated as invalid; `--status` will return `runtime_visibility=installed-only` and `daemon_status=inactive`.
|
||||
5. **`ENOENT` on scheme paths** — The daemon must be running (`redbear-btusb --daemon`) for `scheme:btusb` to exist. After `setrens(0, 0)`, the scheme is isolated in a null namespace.
|
||||
@@ -0,0 +1,37 @@
|
||||
# redbear-dnsd — Operator Runbook
|
||||
|
||||
**Daemon:** redbear-dnsd
|
||||
**Init service:** `/usr/lib/init.d/30_dnsd.service`
|
||||
**Status check:** `cat /scheme/dns` (scheme reachability), `ls /scheme/dns/resolv` (forwarder status)
|
||||
**Restart:** `init-svc restart dnsd`
|
||||
|
||||
## Logs
|
||||
- Destination: `stderr` (visible via `journalctl -u dnsd`)
|
||||
- Debug: `REDBEAR_DNSD_LOG=debug redbear-dnsd`
|
||||
- Trace: `REDBEAR_DNSD_LOG=trace redbear-dnsd`
|
||||
|
||||
## Architecture
|
||||
- **Scheme:** `/scheme/dns` — FSScheme for DNS resolution
|
||||
- **Loopback listener:** UDP port 53 on 127.0.0.1 — standard resolver port for relibc
|
||||
- **mDNS responder:** Background thread, sends multicast DNS responses for the local hostname
|
||||
- **netcfg nameserver subscription:** Watches `/scheme/netcfg/resolv/nameserver` for upstream DNS server changes (DHCP renewal)
|
||||
|
||||
## Runtime State Query
|
||||
- Upstream nameserver: `cat /scheme/netcfg/resolv/nameserver`
|
||||
- Hostname: `cat /etc/hostname`
|
||||
- Cache state: Internal in-memory `DnsCache` + `NegativeCache` (not exposed via scheme yet)
|
||||
- Forwarder config: Defaults to `8.8.8.8`; overridden by netcfg nameserver at startup
|
||||
|
||||
## Signals / SIGTERM Behavior
|
||||
- No SIGTERM handler. Daemon uses `INIT_NOTIFY` fd for scheme-ready notification. On socket close, daemon exits cleanly.
|
||||
|
||||
## Cache
|
||||
- **DnsCache**: Positive responses cached with TTL-based expiry
|
||||
- **NegativeCache**: NXDOMAIN responses cached with SOA MINIMUM TTL
|
||||
|
||||
## Common Issues
|
||||
1. **Relibc can't resolve hostnames** — Verify loopback listener started (`dnsd: loopback DNS listener on 127.0.0.1:53` in logs). If missing, UDP bind may have failed. Ensure `/scheme/dns` scheme is registered.
|
||||
2. **No upstream resolution** — Check netcfg nameserver: `cat /scheme/netcfg/resolv/nameserver`. If empty, the daemon falls back to the hardcoded default (`8.8.8.8`). Ensure network is up.
|
||||
3. **`cannot open /scheme/netcfg/resolv/nameserver for subscription`** — netcfg scheme not available; the daemon will use its default upstream servers. Upstream changes from DHCP renewals won't be detected.
|
||||
4. **mDNS not responding** — The mDNS responder runs in a background thread. Check logs for bind errors. The hostname defaults to `redbear` if `/etc/hostname` is missing.
|
||||
5. **Loopback send failures** — If the loopback thread logs `send_to(...) failed`, the DNS client (relibc) may have closed its socket before a response was ready. Transient on slow upstream lookups.
|
||||
@@ -0,0 +1,54 @@
|
||||
# redbear-ime — Operator Runbook
|
||||
|
||||
**Daemon:** redbear-ime
|
||||
**Init service:** `/usr/lib/init.d/61_ime.service`
|
||||
**Status check:** `cat /scheme/ime/state`
|
||||
**Restart:** `init-svc restart ime`
|
||||
|
||||
## Logs
|
||||
- Destination: `stderr` (tagged `[ime]`)
|
||||
- No env-var log level control; all messages are `INFO` or `ERROR` level.
|
||||
|
||||
## Scheme
|
||||
- **Scheme name:** `ime`
|
||||
- **Root:** `/scheme/ime/` (directory, mode 0555)
|
||||
|
||||
## Scheme Paths
|
||||
| Path | Type | Mode | Description |
|
||||
|------|------|------|-------------|
|
||||
| `state` | file | 0644 | Read-only: `composing=`, `preedit=`, `committed=` |
|
||||
| `compose` | file | 0644 | Write: feed key events (`feed <scancode> <pressed> [shift] [altgr]`) or `reset` to clear state |
|
||||
| `candidates` | file | 0644 | Read-only: tab-separated compose candidate list |
|
||||
|
||||
## Compose Engine
|
||||
- **Current engine:** `BasicLatinEngine` (hardcoded, no config selection yet)
|
||||
- **Dead key trigger:** Scancode 0x5D (apps/menu key). Cycles through grave, acute, circumflex, diaeresis, caron dead keys.
|
||||
- **Compose table:** Supports à/è/ì/ò/ù (grave), á/é/í/ó/ú (acute), â/ê/î/ô/û (circumflex), ä/ë/ï/ö/ü (diaeresis), ǎ/ě/ǐ/ǒ/ǔ (caron).
|
||||
- **US QWERTY layout:** Hardcoded scancode-to-char mapping in `BasicLatinEngine::scancode_to_char`
|
||||
|
||||
## Writing to `compose`
|
||||
```
|
||||
# Feed a key press (scancode, pressed, shift, altgr)
|
||||
feed 0x1E 1 0 0 # 'a' press
|
||||
feed 0x1E 0 0 0 # 'a' release
|
||||
|
||||
# Feed a shift-modified key
|
||||
feed 0x1E 1 1 0 # 'A' press
|
||||
|
||||
# Feed a dead key sequence
|
||||
feed 0x5D 1 0 0 # dead key toggle (grave)
|
||||
feed 0x12 1 0 0 # 'e' → 'è'
|
||||
|
||||
# Reset compose state
|
||||
reset
|
||||
```
|
||||
|
||||
## Signals / SIGTERM Behavior
|
||||
- No SIGTERM handler. Scheme socket close triggers clean exit. Registered via `register_sync_scheme`.
|
||||
|
||||
## Common Issues
|
||||
1. **`failed to register scheme:ime`** — Another daemon already registered the scheme name. Kill the existing instance first.
|
||||
2. **Dead key compose not working** — The compose key is scancode 0x5D (apps/menu). Ensure the input stack sends this scancode. The engine cycles through 5 dead key types (grave/acute/circumflex/diaeresis/caron) — press the compose key multiple times to select the desired accent.
|
||||
3. **Committed text not appearing** — Read `/scheme/ime/state` to verify `committed=` has the expected character. The daemon accumulates committed output in memory; the compositor must read `state` to retrieve it.
|
||||
4. **`BasicLatinEngine` is the only engine** — No engine selection mechanism exists. Latin-based scripts only (ASCII + Latin-1 Supplement composed characters). CJK, Indic, Arabic, etc. are not supported in the current `BasicLatinEngine`.
|
||||
5. **Key releases (pressed=0) do nothing** — The engine only processes key presses (`pressed=1`). Always send both press and release events for compatibility with future engines that may track press duration.
|
||||
@@ -0,0 +1,55 @@
|
||||
# redbear-keymapd — Operator Runbook
|
||||
|
||||
**Daemon:** redbear-keymapd
|
||||
**Init service:** `/usr/lib/init.d/62_keymapd.service`
|
||||
**Status check:** `cat /scheme/keymap/active`
|
||||
**Restart:** `init-svc restart keymapd`
|
||||
|
||||
## Logs
|
||||
- Destination: `stderr` (tagged `[keymapd]`)
|
||||
- No env-var log level control; all messages are `INFO` or `ERROR` level. Keymap load success/failure is logged at startup.
|
||||
|
||||
## Scheme
|
||||
- **Scheme name:** `keymap`
|
||||
- **Root:** `/scheme/keymap/` (directory, mode 0555)
|
||||
|
||||
## Scheme Paths
|
||||
| Path | Type | Mode | Description |
|
||||
|------|------|------|-------------|
|
||||
| `active` | file | 0644 | R/W: current keymap name. Read returns `name=<keymap>`. Write a keymap name to switch. |
|
||||
| `list` | file | 0644 | Read-only: newline-separated list of available keymap names |
|
||||
| `keymap/<name>` | file | 0644 | Read-only: per-keymap detail (entries, compose, dead_keys, sample codepoints) |
|
||||
| `set/<name>` | action | — | Open this path to activate keymap `<name>` (alternative to writing `active`) |
|
||||
|
||||
## Built-in Keymaps (always available)
|
||||
| Name | Description |
|
||||
|------|-------------|
|
||||
| `us` | US QWERTY (default) |
|
||||
| `gb` | UK QWERTY |
|
||||
| `dvorak` | Dvorak simplified layout |
|
||||
| `azerty` | French AZERTY |
|
||||
| `bepo` | French Bépo ergonomic layout |
|
||||
| `it` | Italian QWERTY |
|
||||
|
||||
## Configuration
|
||||
- **`KEYMAP_DIR`** — Directory to scan for JSON keymap files (default: `/etc/keymaps`)
|
||||
- **`XKB_CONFIG_ROOT`** — xkbcommon XKB data directory (e.g. `/usr/share/X11/xkb`). If set, the daemon loads an XKB keymap.
|
||||
- **`XKB_DEFAULT_LAYOUT`** — XKB layout name (default: `us`)
|
||||
- **`XKB_DEFAULT_VARIANT`** — Optional XKB variant (e.g. `dvorak`, `intl`)
|
||||
|
||||
## JSON Keymap Format
|
||||
Keymap files in `KEYMAP_DIR` must have `.json` extension. The daemon calls `Keymap::from_json(&name, &json_str)` to parse each file. The JSON format is documented in `keymap.rs`.
|
||||
|
||||
## Scancode Translation
|
||||
- `translate(scancode: u8, shift: bool, altgr: bool) -> char`
|
||||
- Sample: `cat /scheme/keymap/active` shows `sample_scancode_30=` (scancode 0x1E = 'a' key, unshifted)
|
||||
|
||||
## Signals / SIGTERM Behavior
|
||||
- No SIGTERM handler. Scheme socket close triggers clean exit. Registered via `register_sync_scheme`.
|
||||
|
||||
## Common Issues
|
||||
1. **`failed to register scheme:keymap`** — Another daemon already registered the scheme name.
|
||||
2. **`failed to load keymaps from <dir>`** — The directory does not exist or contains invalid JSON. Check file permissions and JSON syntax. The error is non-fatal; built-in keymaps are always available.
|
||||
3. **XKB keymap not loading** — Requires `XKB_CONFIG_ROOT` to point at a valid xkbcommon data tree. The daemon calls `xkb::load_xkb_keymap()` which reads `keycodes/`, `symbols/`, `types/`, `compat/` subdirectories. Without `XKB_CONFIG_ROOT`, only built-in + JSON keymaps are available.
|
||||
4. **Keymap switch not taking effect** — Write the keymap name to `/scheme/keymap/active` or open `/scheme/keymap/set/<name>`. Verify the name exists in `cat /scheme/keymap/list`. The compositor/terminal must re-read the active keymap after a switch — the daemon only updates its internal state.
|
||||
5. **`sample_scancode_30` shows 'a' when expecting another character** — Verify the keymap is actually active (`cat /scheme/keymap/active` returns `name=<expected>`). If `active` shows the correct keymap, check the keymap's own scancode table (`cat /scheme/keymap/keymap/<name>`).
|
||||
@@ -0,0 +1,48 @@
|
||||
# redbear-polkit — Operator Runbook
|
||||
|
||||
**Daemon:** redbear-polkit
|
||||
**Init service:** `/usr/lib/init.d/70_polkit.service`
|
||||
**Status check:** `dbus-send --system --dest=org.freedesktop.PolicyKit1 --type=method_call --print-reply /org/freedesktop/PolicyKit1/Authority org.freedesktop.DBus.Properties.Get string:org.freedesktop.PolicyKit1.Authority string:BackendName`
|
||||
**Restart:** `init-svc restart polkit`
|
||||
|
||||
## Logs
|
||||
- Destination: `stderr` (visible via `journalctl -u polkit`)
|
||||
- Verbose authorization logging: Every `CheckAuthorization` call logs `subject_kind`, `uid`, `action_id`, and result.
|
||||
- Connection retry logging: Connection failures emit `redbear-polkit: attempt N/3 failed (...)` on stderr.
|
||||
|
||||
## D-Bus Registration
|
||||
- **Bus:** system
|
||||
- **Well-known name:** `org.freedesktop.PolicyKit1`
|
||||
- **Object path:** `/org/freedesktop/PolicyKit1/Authority`
|
||||
- **Connection retries:** 3 attempts at 1-second intervals. Waits up to 30 seconds for the D-Bus socket to appear.
|
||||
|
||||
## Policy File
|
||||
- **Default path:** `/etc/polkit-1/policy.toml`
|
||||
- **Override:** `REDBEAR_POLKIT_POLICY` env var
|
||||
- **Format:** One action per line: `action_id = user_spec1, user_spec2, ...`
|
||||
- **User spec syntax:**
|
||||
- `*` — match any user
|
||||
- `1000` — match specific UID
|
||||
- `@wheel` — match group membership (from `/etc/group` + `/etc/passwd`)
|
||||
- `!1000` — explicit deny (prefix `!`)
|
||||
- **Comments:** Lines starting with `#` are skipped
|
||||
- **Default behavior:** Unknown actions are denied. UID 0 (root) is always authorized.
|
||||
|
||||
## User/Group Resolution
|
||||
- **`/etc/passwd`** — Default path; override with `REDBEAR_POLKIT_PASSWD`
|
||||
- **`/etc/group`** — Default path; override with `REDBEAR_POLKIT_GROUP`
|
||||
- Group membership check covers both primary GID (from passwd) and supplementary memberships (from group file).
|
||||
|
||||
## D-Bus API
|
||||
See `local/docs/dbus-interfaces/redbear-polkit.md` for the full D-Bus interface specification.
|
||||
|
||||
## Signals / SIGTERM Behavior
|
||||
- SIGTERM handler: Tokio-based signal handler (`tokio::signal::unix`). On receipt, shuts down via watch channel. Daemon exits cleanly with `redbear-polkit: shutdown signal received, exiting cleanly`.
|
||||
- On Redox, the signal handler uses a fallback path (`tokio::signal::ctrl_c()` if `signal(SIGTERM)` fails).
|
||||
|
||||
## Common Issues
|
||||
1. **`timed out waiting for D-Bus socket`** — D-Bus system bus daemon not running. Start `dbus-daemon --system` first. Check `DBUS_STARTER_ADDRESS`, `DBUS_SYSTEM_BUS_ADDRESS`, or default `/run/dbus/system_bus_socket`.
|
||||
2. **Policy file not found** — Default path `/etc/polkit-1/policy.toml`. Create it or override via `REDBEAR_POLKIT_POLICY`. Without a policy file, all non-root actions are denied by default.
|
||||
3. **Group membership check fails for user** — Verify the user exists in `/etc/passwd` (UID parsing requires at least 4 colon-separated fields). Verify the group exists in `/etc/group` (GID in field 2, members in field 3). Group membership covers both primary GID and supplementary memberships.
|
||||
4. **Deny rule not working** — Explicit deny (`!user_spec`) must appear in the same policy line as the allow spec. Order matters: `*, !1000` denies UID 1000. `!1000, *` also denies UID 1000 (explicit deny always overrides explicit allow).
|
||||
5. **Connection attempts 1-3 failing** — D-Bus socket appeared but SASL auth handshake is not ready yet. This is normal for the first 1-2 seconds after `dbus-daemon` starts. The daemon retries automatically.
|
||||
+11
-3
@@ -7,7 +7,10 @@ PREFIX_INSTALL=$(PREFIX)/sysroot/
|
||||
PREFIX_PATH=$(ROOT)/$(PREFIX_INSTALL)/bin
|
||||
BINUTILS_TARGET=recipes/dev/binutils-gdb/target/$(HOST_TARGET)/$(TARGET)
|
||||
LIBTOOL_TARGET=recipes/dev/libtool/target/$(HOST_TARGET)
|
||||
GCC_TARGET=recipes/dev/gcc13/target/$(HOST_TARGET)/$(TARGET)
|
||||
# Which GCC recipe the from-source toolchain path cooks. Override to move
|
||||
# the toolchain to a new GCC (e.g. GCC_RECIPE=gcc16).
|
||||
GCC_RECIPE?=gcc13
|
||||
GCC_TARGET=recipes/dev/$(GCC_RECIPE)/target/$(HOST_TARGET)/$(TARGET)
|
||||
LIBSTDCXX_TARGET=recipes/libs/libstdcxx-v3/target/$(TARGET)/$(HOST_TARGET)
|
||||
RELIBC_FREESTANDING_TARGET=recipes/core/relibc/target/$(TARGET)/$(HOST_TARGET)
|
||||
RELIBC_TARGET=recipes/core/relibc/target/$(TARGET)
|
||||
@@ -110,12 +113,14 @@ else
|
||||
# so ::strtold is visible when the C++ wrapper runs its using.
|
||||
for _cstdlib in "$(COOKBOOK_ROOT)/prefix/${TARGET}/sysroot/${GNU_TARGET}/include/c++"/*/cstdlib; do \
|
||||
[ -f "$$_cstdlib" ] || continue; \
|
||||
grep -q 'Red Bear: relibc declares strtold' "$$_cstdlib" && continue; \
|
||||
sed -i '/^#include_next <stdlib.h>$$/a\\n// Red Bear: relibc declares strtold via cbindgen trailer.\n// The explicit include ensures ::strtold is visible when the\n// C++ wrapper processes its using-directives below.\n#include <stdlib.h>' "$$_cstdlib"; \
|
||||
done
|
||||
@REDOXER_TC=$(HOME)/.redoxer/$(TARGET)/toolchain/$(GNU_TARGET); \
|
||||
if [ -d "$$REDOXER_TC/include/c++" ]; then \
|
||||
for _cstdlib in "$$REDOXER_TC/include/c++"/*/cstdlib; do \
|
||||
[ -f "$$_cstdlib" ] || continue; \
|
||||
grep -q 'Red Bear: relibc declares strtold' "$$_cstdlib" && continue; \
|
||||
sed -i '/^#include_next <stdlib.h>$$/a\\n// Red Bear: relibc declares strtold via cbindgen trailer.\n// The explicit include ensures ::strtold is visible when the\n// C++ wrapper processes its using-directives below.\n#include <stdlib.h>' "$$_cstdlib"; \
|
||||
done; \
|
||||
fi
|
||||
@@ -137,6 +142,7 @@ else
|
||||
# most of the C declarations) but BEFORE the first using-directive.
|
||||
for _cstdlib in "$(PREFIX)/gcc-install/$(GNU_TARGET)/include/c++"/*/cstdlib; do \
|
||||
[ -f "$$_cstdlib" ] || continue; \
|
||||
grep -q 'Red Bear: relibc declares strtold' "$$_cstdlib" && continue; \
|
||||
sed -i '/^#include_next <stdlib.h>$$/a\\n// Red Bear: relibc declares strtold via cbindgen trailer.\n// The explicit include ensures ::strtold is visible when the\n// C++ wrapper processes its using-directives below.\n#include <stdlib.h>' "$$_cstdlib"; \
|
||||
done
|
||||
# Propagate fresh relibc artifacts to the redoxer toolchain at
|
||||
@@ -310,7 +316,7 @@ else
|
||||
export $(PREFIX_CONFIG) PATH="$(ROOT)/$(PREFIX)/libtool-install/bin:$(ROOT)/$(PREFIX)/binutils-install/bin:$$PATH" \
|
||||
COOKBOOK_LIBTOOL_DIR=$(ROOT)/$(PREFIX)/libtool-install COOKBOOK_CROSS_TARGET=$(TARGET) COOKBOOK_CROSS_GNU_TARGET=$(GNU_TARGET) \
|
||||
COOKBOOK_HOST_SYSROOT=/usr COOKBOOK_CROSS_SYSROOT=$(ROOT)/$(PREFIX)/relibc-freestanding-install/$(GNU_TARGET) && \
|
||||
$(REPO_BIN) cook host:gcc13
|
||||
$(REPO_BIN) cook host:$(GCC_RECIPE)
|
||||
cp -r "$(GCC_TARGET)/stage/usr/". "$@.partial"
|
||||
cp -r "$(GCC_TARGET)/stage.cxx/usr/". "$@.partial"
|
||||
cp -r "$(PREFIX)/binutils-install/". "$@.partial"
|
||||
@@ -351,7 +357,9 @@ else
|
||||
cp -r "$(PREFIX)/relibc-freestanding-install/". "$@.partial"
|
||||
cp -r "$(PREFIX)/libtool-install/". "$@.partial"
|
||||
@#TODO: how to make this not conflict with libc?
|
||||
rm -f "$@.partial/lib/gcc/$(GNU_TARGET)/13.2.0/include/limits.h"
|
||||
@# Version-globbed: hardcoding a GCC version here made the rm silently
|
||||
@# no-op after a toolchain upgrade, leaving the conflicting limits.h.
|
||||
rm -f "$@.partial/lib/gcc/$(GNU_TARGET)"/*/include/limits.h
|
||||
# libgcc and freestanding libstdcxx
|
||||
export PATH="$(ROOT)/$@.partial/bin:$$PATH" && \
|
||||
$(MAKE) -C "$(ROOT)/$(GCC_TARGET)/build" all-target-libgcc all-target-libstdc++-v3 && \
|
||||
|
||||
Reference in New Issue
Block a user