The overflow-triggered migration path (a WIREBIND-attached identity's own drive running low on space) was scoped but never built -- only the trigger-detection call site was missing, per this section's own text. - capsule_wirebind.c now tracks the attached blkio_dev* alongside the already-tracked VM id, set in try_attach() and cleared in both EJECT/UNCLEAN paths. - New capsule_wirebind_overflow_idle_check(), called once per idle tick in repl.c right alongside blk_migration_idle_check() (same cadence): reads the attached drive's free/total via blk_get_device_free_blocks(), and if free space is below a fixed 10% threshold, extends the identity's pool with a one-time blk_firsttouch_claim() of 8 additional devblocks on Artemis's system-resident device. - New blk_owner_has_claim(owner_fp) in block_subsystem.c answers the debounce question blk_firsttouch_claim()'s own doc comment had left open: a disk scan, not a RAM flag, so the already-extended answer survives reboot/reattach, matching BMAPFMT's "ownership travels with the block" model. Premise checked before building (does a WIREBIND-attached drive actually give a real free/total signal, or does it stay PROVISIONAL/raw): traced repl.c's attach sequence and confirmed blk_subsys_attach_device() runs on the same dev pointer right after WIREBIND, and a WIREBIND-eligible drive is always already STFR/v2-formatted, so the signal is real. Premise held, unlike the BAM item's overstated one. Verified with the mandatory 3-arch QEMU acceptance (identical dictionary hashes, no regression) plus a live logic test of blk_owner_has_claim(): a temporary TEST-OWNER-CLAIM word, run once via SK_CMD and reverted, confirmed it correctly detects the claiming owner and rejects an unrelated one. The low-disk-space-triggers-a-claim path itself is not verified end-to-end -- that needs a real minted WIREBIND-user thumbdrive with deliberately tiny capacity, out of scope for this pass; noted as such in the FABRIC-2.md §I.2 closure note rather than overclaimed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EjXFo7mPXjUMjfJeuUUz4
151 lines
6.8 KiB
C
151 lines
6.8 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
|
||
Copyright (c) 2023–2025 Robert A. James
|
||
All rights reserved.
|
||
|
||
Licensed under the StarForth License, Version 1.0
|
||
*/
|
||
|
||
/**
|
||
* capsule_wirebind.h - WIREBIND: the real thumbdrive-attach call site
|
||
* (FABRIC-2.md §F.5/§F.23). Assembles pieces already built and
|
||
* individually verified this session -- CERTVERIFY (vm_identity.h's
|
||
* vm_identity_from_cert()), RUNCAP (capsule_runcap.h), the console-VM +
|
||
* user-VM pair (capsule_console.h, sk_repl_dispatch_line() in repl.c) --
|
||
* into one automatic sequence, replacing the RUNCAP-TEST/PAIR-TEST
|
||
* diagnostic words that exercised each piece by hand.
|
||
*/
|
||
|
||
#ifndef STARKERNEL_CAPSULE_WIREBIND_H
|
||
#define STARKERNEL_CAPSULE_WIREBIND_H
|
||
|
||
#ifdef __STARKERNEL__
|
||
|
||
#include "starkernel/homeblocks_sig.h"
|
||
#include "starkernel/vm_identity.h"
|
||
#include "vm.h"
|
||
|
||
struct blkio_dev;
|
||
|
||
/**
|
||
* capsule_wirebind_verify_cert - Read the cert region off dev and verify
|
||
* it against mama_vm's own Zuse identity. Shared by both
|
||
* capsule_wirebind_try_attach() (the original attach) and BINDSTEP
|
||
* (mama_word_use(), mama_forth_words.c -- re-verifies live on every USE
|
||
* of an identity-locked VM, per FABRIC-2.md §F.9 decision 1) so both
|
||
* call sites check the exact same thing the exact same way.
|
||
*
|
||
* No-op-and-fail (-1) if sig->cert_offset is 0 (no cert region -- a
|
||
* genesis-mode Zuse drive, or simply not a regular identity drive) or
|
||
* mama_vm has no installed Zuse cert yet.
|
||
*
|
||
* @param dev Already-open block device to read the cert from.
|
||
* @param sig Its already-checked homeblocks_sig_t.
|
||
* @param mama_vm Hera's own VM -- the trust root (zuse_cert_pubkey).
|
||
* @param out Filled with the verified identity on success.
|
||
* @return 0 on success, -1 on any failure (read, verify, or precondition).
|
||
*/
|
||
int capsule_wirebind_verify_cert(struct blkio_dev *dev,
|
||
const homeblocks_sig_t *sig,
|
||
VM *mama_vm, VMIdentity *out);
|
||
|
||
/**
|
||
* capsule_wirebind_try_attach - Try to verify and bind a just-attached
|
||
* regular (non-Zuse) identity drive.
|
||
*
|
||
* No-op if sig->cert_offset is 0 (a genesis-mode Zuse drive has no cert
|
||
* region -- that's capsule_zuse_boot_try_attach()'s own job, not this
|
||
* one's) or if mama_vm has no installed Zuse cert yet (nothing to verify
|
||
* the attached cert against). Otherwise: reads the cert devblock(s),
|
||
* calls vm_identity_from_cert() against mama_vm's own zuse_cert_pubkey
|
||
* and sig->drive_uuid. On success, reads the drive's own
|
||
* user_identity_seed_t for its username and births a console VM +
|
||
* RUNCAP-born user VM pair (idempotent -- no-ops if that username is
|
||
* already live this session), installs the verified VMIdentity onto the
|
||
* user VM, and registers the "<username>~user" pairing
|
||
* (sk_repl_dispatch_line(), repl.c, looks for this). Does NOT USE the
|
||
* new console automatically -- that stays an explicit, later,
|
||
* ACL-gated step (BINDSTEP, §F.9), not something a bare attach should
|
||
* trigger silently.
|
||
*
|
||
* @param dev The just-attached, already-open block device.
|
||
* @param sig Its already-checked homeblocks_sig_t.
|
||
* @param mama_vm Hera's own VM (the verifier -- her zuse_cert_pubkey is
|
||
* the trust root regular user certs are checked against).
|
||
*/
|
||
void capsule_wirebind_try_attach(struct blkio_dev *dev,
|
||
const homeblocks_sig_t *sig,
|
||
VM *mama_vm);
|
||
|
||
/**
|
||
* capsule_wirebind_eject - Graceful detach of whatever VM is currently
|
||
* attached via the home-blocks USB path (FABRIC-2.md §F.10, decision 1).
|
||
* The drive is still physically present when this runs.
|
||
*
|
||
* Sequence: resolve the tracked attached-VM id to a live registry entry
|
||
* (no-op, returns -1, if nothing is tracked or the entry is already
|
||
* dead/gone -- capsule_vm_kill()'s own idempotency covers a VM already
|
||
* killed by some other path); blk_vm_flush_all() while the VM is still
|
||
* alive; if the console's active VM is this same VM, reset it to Hera
|
||
* (sk_repl_set_active_vm(NULL)) *before* teardown -- required, not
|
||
* optional, to avoid a dangling console pointer; capsule_vm_kill() by
|
||
* name; clear the tracked state.
|
||
*
|
||
* Single-USB-device constraint (§F.8) means there is never more than one
|
||
* candidate, so this always targets "whatever's currently attached" --
|
||
* no name argument.
|
||
*
|
||
* @return 0 on success, -1 if nothing was attached to eject.
|
||
*/
|
||
int capsule_wirebind_eject(void);
|
||
|
||
/**
|
||
* capsule_wirebind_unclean_detach - Abrupt-path counterpart to
|
||
* capsule_wirebind_eject() (FABRIC-2.md §F.10, decision 2 -- the UNCLEAN
|
||
* node, closed alongside EJECT). Called from the existing
|
||
* bot_msc_detach_pending hot-unplug signal (repl.c) -- the device is
|
||
* already gone by the time this runs, so no flush is attempted; data
|
||
* since the last flush is lost, which is correct unclean-removal
|
||
* semantics. Otherwise identical to capsule_wirebind_eject(): same
|
||
* active-VM reset-before-kill step, same tracked-state clear.
|
||
*/
|
||
void capsule_wirebind_unclean_detach(void);
|
||
|
||
/**
|
||
* capsule_wirebind_attached_username - The plain username (no "~user"
|
||
* registry-name suffix) of whichever identity is currently tracked as
|
||
* attached, or NULL if none is (FABRIC-2.md §I.1/4.4s -- the `(user)`
|
||
* console prompt segment reads this). Points into WIREBIND's own
|
||
* internal storage; valid only until the next attach/eject/detach, same
|
||
* caveat as console_get_vm_name().
|
||
*/
|
||
const char *capsule_wirebind_attached_username(void);
|
||
|
||
/**
|
||
* capsule_wirebind_overflow_idle_check - FABRIC-2.md §I.2's own "overflow
|
||
* trigger," decided and built 2026-09-05. Called once per idle tick
|
||
* (sk_repl_idle(), repl.c, alongside blk_migration_idle_check() -- same
|
||
* ~1 Hz cadence), same as that function's own convention.
|
||
*
|
||
* No-op if nothing is attached via WIREBIND. Otherwise reads the attached
|
||
* drive's own free/total via blk_get_device_free_blocks() (real numbers:
|
||
* a WIREBIND-attached drive is always HOMEBLOCKS_SIG_OK, i.e. already
|
||
* STFR/v2-formatted, by the time blk_subsys_attach_device() runs on the
|
||
* same dev pointer right after WIREBIND itself -- not PROVISIONAL, not
|
||
* raw). If free space is below a fixed threshold AND the attached
|
||
* identity does not already own a claim (blk_owner_has_claim() -- a disk
|
||
* scan, not a RAM flag, so this decision survives reboot/reattach for
|
||
* free), claims a fixed number of additional devblocks on Artemis's own
|
||
* device via blk_firsttouch_claim() -- a one-time-per-identity extension,
|
||
* not a growth loop, deliberately: this does not free space on the
|
||
* user's own drive, it only extends their pool onto system-resident
|
||
* space, so re-claiming every tick once already extended would walk
|
||
* Artemis's device to exhaustion for no benefit.
|
||
*/
|
||
void capsule_wirebind_overflow_idle_check(void);
|
||
|
||
#endif /* __STARKERNEL__ */
|
||
|
||
#endif /* STARKERNEL_CAPSULE_WIREBIND_H */
|