The family gate (decisions 63/64, R-780): family members with their own logins, a permanent forwardAuth door per family app, anchored exceptions, min_controller
gates / gates (push) Successful in 27s

- internal/family: the family list (bcrypt, generated 4x4 passwords shown once) + 30-day sessions in family.json
  (0600, atomic); a reset (generation), a removal or a logout ends sessions at the next request.
- internal/stacks/family_gate.go: family_gate / family_gate_except / min_controller in .felhom.yml; the door is written
  BEFORE the first start (install and a removed app's restore), a life record in app.yaml, reconciled by the gate loop;
  priority below the install hold, setup gate and sign-up block; every exception anchored ^/prefix(/|$) (finding F1).
- internal/web/family_gate.go: forwardAuth /__felhom_gate/family (app cookie felhom_famgate, host-only, names a store
  session); /__family/start|login|logout on the dashboard host (session cookie felhom_family, Path=/__family);
  sign-in counted per visitor (clientIP) AND per name, short windows; the household's dashboard session vouches.
  RequireAuth never reads a family cookie. The "Család" card on the security page: add / new password / remove.
Red-proofs RP-F1..RP-F7 (felhom.eu audits/family-gate-2026-10-02/A/).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-02 07:42:47 +02:00
parent a4a753b9e2
commit 977665d8c0
25 changed files with 2168 additions and 10 deletions
+9 -2
View File
@@ -65,8 +65,15 @@ type Metadata struct {
// setup gate opens. See signup_block.go.
SignupBlock string `yaml:"signup_block,omitempty" json:"signup_block,omitempty"`
// AfterSetup (v0.282.0, decisions 47/49): the app's OWN sign-up switch, set when the gate opens. See after_setup.go.
AfterSetup *AfterSetupSpec `yaml:"after_setup,omitempty" json:"after_setup,omitempty"`
Integrations []IntegrationDef `yaml:"integrations,omitempty" json:"integrations,omitempty"`
AfterSetup *AfterSetupSpec `yaml:"after_setup,omitempty" json:"after_setup,omitempty"`
// FamilyGate (v0.287.0, `09` §3 decisions 63/64): a PERMANENT gate — only family members (and the household) reach
// the app; FamilyGateExcept are literal path prefixes a phone/e-reader app calls, left to the app's own login
// (anchored at a segment boundary). See family_gate.go.
FamilyGate bool `yaml:"family_gate,omitempty" json:"family_gate,omitempty"`
FamilyGateExcept []string `yaml:"family_gate_except,omitempty" json:"family_gate_except,omitempty"`
// MinController (v0.287.0): the lowest box software that installs this template correctly; a lower one refuses.
MinController string `yaml:"min_controller,omitempty" json:"min_controller,omitempty"`
Integrations []IntegrationDef `yaml:"integrations,omitempty" json:"integrations,omitempty"`
// InitialCreds: for apps that auto-generate a first-login credential into a file inside the
// container (e.g. Crafty's default-creds.txt). The controller reads + parses that file live and
// surfaces it on the app page, so the customer never has to dig through logs. Optional.