Testing modes, TTLs, and credential checks — zero secrets¶
The interesting behaviour of modes — TTL expiry, dependent switches lowered along
with it, token services starting and stopping as the mode changes, credential checks going
DEGRADED and recovering — normally needs real credentials and real waiting to see. This rig
removes both: a fake credential plugin and a mode clock you can fast-forward. Everything
below runs on any computer with fy installed, with no secrets anywhere.
(A mode is a set of switches, each at a level. Terms are in the glossary.)
New to modes? Start with the example project's mode walkthrough: the same rig driving a real stack (a refused combination → the one-command fix → an overlay → a visible feature). This page goes a level deeper: TTLs, the expiry cascade, and credential checks lapsing and recovering.
The pieces¶
[plugins.fakecred] — declare it in foldyard.toml, or in your gitignored
foldyard.local.toml to keep it off teammates' dashboards. It adds:
- a
fakecredswitch (off | on | user): onruns the fake token service, a small HTTP server handing out dummy tokens (set up per project like the real ones, so leftover-process cleanup works on it too);useris an emergency level: it has a TTL and switches itself off.- a
fakedepswitch (off | on):onrequiresfakecredto beonoruser. The plugin declares this as data (Switch.requires), the same way a real plugin or your[[require]]table would. So whenfakecredexpires,fakedephas to come down with it — that's the expiry cascade. - a credential check (every 2 s) reading
~/.foldyard/<project>/fakecred-capability: missing orokmeans working; anything else means lapsed, and the content is shown as the DEGRADED detail. While lapsed, the fake token service's/tokenreturns 403 — the same shape as a real credential that has expired.
fy clock — shifts foldyard's clock for everything that reads it: TTL expiry, countdowns,
the supervisor's automatic switch-off.
fy clock ff 2h— fast-forward;fy clock reset— back to real time;fy clock— show the current shift.
Only your computer can change it; the offset is stored outside the repo, so nothing in the box can shift it. The credential checks' intervals stay on real time, so fast-forwarding expires TTLs without firing every check at once.
The walkthrough¶
fy mode fakecred=user fakedep=on ttl=1h # emergency level + a dependent switch
fy host restart # (or fy up) — starts the fake token service
curl -s http://127.0.0.1:$(fy mode | grep -o ':[0-9]*' | head -1 | tr -d :)/token
# a dummy token, while the credential "works"
echo lapsed > ~/.foldyard/<project>/fakecred-capability
sleep 4 # the check runs every ~2 s — give it a tick or two
fy mode # → fakecred user … ⚠ DEGRADED — fake capability lapsed (…) + the fix
fy state # → a ✗ capability row; the supervisor log has the ok → DEGRADED change,
# and /token now returns 403: a lapsed credential, made visible
echo ok > ~/.foldyard/<project>/fakecred-capability # "run the fix"
sleep 4 # same interval on the way back
# → "capability … recovered" in the log; fy mode drops the DEGRADED marker
fy clock ff 2h # the TTL has now expired
# within a tick the supervisor logs:
# TTL expiry strands dependent switches — settling fakedep=off
# TTL expired → fakecred=off, fakedep=off
# stopped fake-minter
fy mode # → everything off, and consistent (fakedep came down WITH the expiry)
fy clock reset
Follow the supervisor log with fy host logs -f while you go.
What each step tests¶
| step | what it exercises |
|---|---|
fy mode fakecred=user … ttl |
emergency levels, TTL recording, refusing combinations that can't work (all switches set together) |
fy host restart starts the service |
the supervisor reacting to the mode, starting a per-project token service |
| lapse file → DEGRADED | credential checks: plugin → supervisor → capabilities.json → mode mirror → fy mode / fy state |
echo ok → recovered |
logging the change, the dashboard recovering |
fy clock ff 2h |
expiry, the supervisor's switch-off, the expiry cascade (devmode.settle_incoherent), stopping the service |
kill -9 the supervisor, restart |
cleaning up the leftover fake token service (_is_our_daemon matches its per-project path) |
The same plugin backs the unit tests (tests/test_fakecred.py, plus the check, cascade and clock
tests in test_devmode.py / test_supervisor.py): it is the live twin of those tests, not a
separate mechanism.
DEGRADED vs changing the mode — the design line¶
A lapsed credential does not change the mode. The mode is what you asked for; whether the
credential works is observed. Lowering the mode on a lapse would lose what you asked for (you'd
have to notice and set it again after fixing the credential), flip back and forth on brief
failures, and turn a read-only check into something that writes. So a lapse shows as
⚠ DEGRADED on the level you asked for, with the fix in the message, and recovers in place.
The only thing that does write the mode is TTL expiry of an emergency level — your own credentials must never quietly stay on — and the cascade that rides the same write: a dependent switch the expiry would leave in a combination that can't work is lowered to its default too. So an expiry always ends in a mode that works offline.