diff --git a/cmd/binding.go b/cmd/binding.go index 4dcc8e1..46a1082 100644 --- a/cmd/binding.go +++ b/cmd/binding.go @@ -6,14 +6,17 @@ package cmd import ( "context" "encoding/json" + "errors" "fmt" "io" "os" + "strings" "syscall" "time" "github.com/ori-platform/ori-cli/internal/binding" "github.com/ori-platform/ori-cli/internal/capture" + "github.com/ori-platform/ori-cli/internal/output" "github.com/spf13/cobra" ) @@ -97,6 +100,17 @@ cannot name hardware the device does not have. Nothing is inferred: the three commissioned outcomes are asked separately, a contact type is not among the questions, and polarity is answered rather than defaulted. +On a device with a binding in force, a change is a revision of it. The binding +in force is read from the runtime, or with --revise from a file for preparation +away from the device; either way it is used only when its canonical hash and +sequence are the ones the runtime reports. Each fact is shown as that binding +records it and asked only whether it changed; what did not is carried, and the +prior value of what did is carried into the reason. A change to anything but +the rated capacity or inventory generation, or hardware replaced like for like, +needs fresh proof legs. Those can be proven only on a line no zone of the +binding in force drives, so such a change on a driven line is refused as soon +as it is declared. + The draft is unsigned and incomplete by design. Signing is a separate step with its own key custody.`, Args: cobra.NoArgs, @@ -117,13 +131,22 @@ its own key custody.`, if err != nil { return fmt.Errorf("failed to read --force: %w", err) } - return runBindingCapture(state, cmd.InOrStdin(), path, zone, out, force) + revise, err := cmd.Flags().GetString("revise") + if err != nil { + return fmt.Errorf("failed to read --revise: %w", err) + } + if cmd.Flags().Changed("revise") && revise == "" { + return errors.New("--revise names the signed binding in force; it was given empty") + } + return runBindingCaptureRevising(state, cmd.InOrStdin(), path, zone, out, force, revise) }, } captureCmd.Flags().String("path", "ori.yaml", "path to the runtime configuration") captureCmd.Flags().String("zone", "", "the zone this binding covers") captureCmd.Flags().String("out", "", "write the draft here instead of stdout") captureCmd.Flags().Bool("force", false, "overwrite an existing draft") + captureCmd.Flags().String("revise", "", + "read the binding in force from this signed envelope instead of the runtime") _ = captureCmd.MarkFlagRequired("zone") deliverCmd := &cobra.Command{ @@ -186,6 +209,14 @@ installer can see before capturing what this device will accept.`, // writes can be mistaken for a document a runtime would accept. func runBindingCapture( state *rootState, in io.Reader, path, zone, out string, force bool, +) error { + return runBindingCaptureRevising(state, in, path, zone, out, force, "") +} + +// runBindingCaptureRevising is capture, and when revise names the binding in +// force, a revision of it. +func runBindingCaptureRevising( + state *rootState, in io.Reader, path, zone, out string, force bool, revise string, ) error { ctx, cancel := context.WithTimeout(context.Background(), exportTimeout) defer cancel() @@ -205,6 +236,9 @@ func runBindingCapture( return fmt.Errorf("the runtime inventory is not readable: %w", decodeErr) } + if err := checkChain(inv); err != nil { + return err + } // Checked before a single question, so an operator does not answer nine of // them at a panel to be told the path was in the way. if out != "" { @@ -213,16 +247,68 @@ func runBindingCapture( } } + // A binding in force makes every change a revision, captured against that + // binding: from the runtime's export, or from --revise when preparing away + // from the device. Neither route is trusted until the document is the one + // the inventory reports in force. + var prior capture.Prior + var refs []binding.ActuatorRef + revising := inv.AcceptedBindingHash != "" + if revise != "" && !revising { + return refusedError{fmt.Errorf( + "device %q reports no binding in force, so there is nothing to revise; "+ + "capture a first binding without --revise", inv.DeviceID)} + } + if revising { + loaded, priorErr := loadPrior(state, ctx, path, revise, inv) + if priorErr != nil { + return priorErr + } + declared, refsErr := capture.DeclaredRefs(inv) + if refsErr != nil { + return fmt.Errorf("the runtime inventory is not readable: %w", refsErr) + } + prior, refs = loaded, declared + } + asker := capture.NewTerminalAsker(in, state.stderr) - draft, captureErr := capture.Capture(asker, inv, zone, state.nowMs()) - if captureErr != nil { - return refusedError{captureErr} + var draft binding.Binding + var revision *capture.Revision + if !revising { + captured, captureErr := capture.Capture(asker, inv, zone, state.nowMs()) + if captureErr != nil { + return refusedError{captureErr} + } + draft = captured + } else { + revised, rev, reviseErr := capture.Revise(asker, inv, prior, zone, state.nowMs()) + if reviseErr != nil { + return refusedError{reviseErr} + } + // The verifier's own stages over the draft, against what the runtime + // retained: a revision the runtime would refuse is refused here, before + // a signature exists. + if checkErr := revised.CheckRevision(binding.RetainedState(prior.Accepted), binding.Context{ + DeclaredSensorIDs: inv.SensorIDs, + DeclaredActuators: refs, + DeploymentPosture: inv.DeploymentPosture, + }); checkErr != nil { + return refusedError{fmt.Errorf( + "the runtime would refuse this revision (%v); nothing was written", checkErr)} + } + draft, revision = revised, &rev } encoded, encodeErr := capture.DraftJSON(draft) if encodeErr != nil { return fmt.Errorf("failed to encode the draft: %w", encodeErr) } + if state.json { + return reportCapturedJSON(state, encoded, out, force, revision) + } + if revision != nil { + reportRevision(state.stderr, *revision) + } if out == "" { _, writeErr := state.stdout.Write(append(encoded, '\n')) return writeErr @@ -234,6 +320,111 @@ func runBindingCapture( return nil } +// loadPrior reads the binding in force from the runtime's export, or from the +// file --revise names, and binds it to the inventory's account of it. +func loadPrior( + state *rootState, ctx context.Context, path, revise string, inv capture.Inventory, +) (capture.Prior, error) { + if revise != "" { + // Standard input carries the ceremony's answers; it cannot also carry + // the document they are measured against. + if revise == "-" { + return capture.Prior{}, errors.New( + "--revise names a file; standard input carries the ceremony's answers") + } + raw, err := readDocument(nil, revise) + if err != nil { + return capture.Prior{}, err + } + prior, err := capture.LoadPrior(inv, raw) + if err != nil { + return capture.Prior{}, refusedError{err} + } + return prior, nil + } + payload, err := invokeBridgeEchoing(state, ctx, []string{ + "commissioning", "binding-export", "--path", path, + }, false) + if err != nil { + return capture.Prior{}, err + } + raw, err := json.Marshal(payload["result"]) + if err != nil { + return capture.Prior{}, fmt.Errorf("failed to re-encode the binding export: %w", err) + } + prior, err := capture.LoadExported(inv, raw) + if err != nil { + return capture.Prior{}, refusedError{err} + } + return prior, nil +} + +// checkChain refuses an inventory whose account of the chain contradicts +// itself. The runtime reports both values from the one binding in force, so a +// sequence without a hash, or the reverse, is not a device state. +func checkChain(inv capture.Inventory) error { + if (inv.AcceptedBindingSeq == 0) != (inv.AcceptedBindingHash == "") || inv.AcceptedBindingSeq < 0 { + return fmt.Errorf( + "the runtime inventory reports binding_seq %d with hash %q; a binding in "+ + "force has both and a device without one has neither", + inv.AcceptedBindingSeq, inv.AcceptedBindingHash) + } + if inv.AcceptedBindingHash != "" && !binding.IsDigest(inv.AcceptedBindingHash) { + return fmt.Errorf( + "the runtime inventory reports %q as the binding in force, which is not a "+ + "canonical hash", inv.AcceptedBindingHash) + } + return nil +} + +// reportCapturedJSON emits the one object JSON mode promises. +func reportCapturedJSON( + state *rootState, encoded []byte, out string, force bool, revision *capture.Revision, +) error { + result := map[string]any{} + if revision != nil { + result["revision"] = revision + } + if out == "" { + result["draft"] = json.RawMessage(encoded) + } else { + if writeErr := writeDraft(out, append(encoded, '\n'), force); writeErr != nil { + return writeErr + } + result["path"] = out + } + return output.JSON(state.stdout, map[string]any{"ok": true, "result": result}) +} + +// reportRevision says what the revision changed, carried, and needs. +func reportRevision(w io.Writer, rev capture.Revision) { + fmt.Fprintf(w, "\nrevision of binding %d (%s) as binding %d, zone %q\n", + rev.SupersedesSeq, rev.Supersedes, rev.BindingSeq, rev.ZoneID) + for _, c := range rev.Changed { + fmt.Fprintf(w, " changed: %s: %s -> %s\n", c.Fact, c.Was, c.Now) + } + if len(rev.Changed) == 0 { + fmt.Fprintf(w, " changed: nothing\n") + } + fmt.Fprintf(w, " carried: %s\n", listOrNone(rev.Carried)) + fmt.Fprintf(w, " other zones carried unchanged: %s\n", listOrNone(rev.CarriedZones)) + if rev.FreshProof { + fmt.Fprintf(w, " fresh proof required by: %s\n", strings.Join(rev.Because, ", ")) + } + fmt.Fprintf(w, " circuit leg: %s; control leg: %s\n", rev.CircuitLeg, rev.ControlLeg) + fmt.Fprintf(w, " zone %q proof once delivered: %s\n", rev.ZoneID, rev.ProofState) + fmt.Fprintf(w, " trip-point bound (capacity times the release's multiplier, against "+ + "full scale): not checked here, decided at delivery\n") + fmt.Fprintf(w, " reason: %s\n", rev.Reason) +} + +func listOrNone(values []string) string { + if len(values) == 0 { + return "none" + } + return strings.Join(values, ", ") +} + // runBindingDeliver hands a signed envelope to the runtime and reports its verdict. func runBindingDeliver(state *rootState, path, file string, force bool) error { ctx, cancel := context.WithTimeout(context.Background(), exportTimeout) diff --git a/cmd/binding_revise_test.go b/cmd/binding_revise_test.go new file mode 100644 index 0000000..71d2919 --- /dev/null +++ b/cmd/binding_revise_test.go @@ -0,0 +1,1138 @@ +// Copyright 2026 Ori Nexus Systems LTD +// SPDX-License-Identifier: Apache-2.0 + +package cmd + +import ( + "context" + "crypto/ed25519" + "encoding/json" + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/ori-platform/ori-cli/internal/binding" + "github.com/ori-platform/ori-cli/internal/bridge" + "github.com/ori-platform/ori-cli/internal/capture" +) + +const ( + priorProofAt = int64(1700000000000) + priorControlAt = int64(1700000100000) + reviseNow = int64(1800000000000) +) + +var revisionKey = ed25519.NewKeyFromSeed([]byte("ori-cli-revision-test-seed-32byt")) + +func intPtr(v int) *int { return &v } +func boolPtr(v bool) *bool { return &v } + +// provenZone is a zone with both legs proven, as a binding in force has. +func provenZone(zoneID, sensorID string, pin int, activeHigh bool) binding.Zone { + openCoil, closeCoil := binding.CoilEnergised, binding.CoilDeEnergised + levelFor := func(coil string) string { + if (coil == binding.CoilEnergised) == activeHigh { + return binding.GPIOLevelHigh + } + return binding.GPIOLevelLow + } + observations := func(withLevel bool) []binding.Observation { + open := binding.Observation{ + Commanded: binding.OutcomeOpen, CoilState: openCoil, + TerminalStateObserved: binding.CircuitOpen, LoadPresentBefore: true, + } + closeObs := binding.Observation{ + Commanded: binding.OutcomeClose, CoilState: closeCoil, + TerminalStateObserved: binding.CircuitClosed, LoadPresentAfter: true, + } + if withLevel { + open.GPIOLevel, closeObs.GPIOLevel = levelFor(openCoil), levelFor(closeCoil) + } + return []binding.Observation{open, closeObs} + } + return binding.Zone{ + ZoneID: zoneID, + RatedCapacity: binding.RatedCapacity{ + Parameter: "rated_capacity_amps", Value: 10, Provenance: binding.ProvenanceNameplate, + }, + Sensor: binding.Sensor{ + SensorID: sensorID, Quantity: "current", Unit: "ampere", RangeMin: 0, + RangeMax: 100, Direction: "positive_is_load_draw", NoiseFloor: 0.05, + CalibrationRef: "cal-" + zoneID, + }, + Actuator: binding.Actuator{ + Kind: binding.KindLocalGPIO, + Identity: binding.Identity{GPIOPin: intPtr(pin), ActiveHigh: boolPtr(activeHigh)}, + Mapping: binding.Mapping{ + OpenProtectedCircuit: openCoil, CloseProtectedCircuit: closeCoil, + DeEnergisedTerminalState: binding.CircuitClosed, + }, + }, + Proof: binding.Proof{ + Method: binding.MethodPreEnergy, PerformedAtMs: priorProofAt, + Observations: observations(false), + ControlPath: &binding.ControlPath{ + Method: binding.ControlCommanded, PerformedAtMs: priorControlAt, + Observations: observations(true), + }, + }, + } +} + +// device holds a signed binding in force, and answers the two bridge commands +// a revision reads as the runtime would. +type device struct { + envelope []byte + accepted *binding.Accepted + inv map[string]any + // export overrides the binding-export answer when set. + export string + calls [][]string +} + +func signedBinding(t *testing.T, seq int64, supersedes *string, zones ...binding.Zone) []byte { + t.Helper() + return signedBindingAt(t, seq, supersedes, 1, zones...) +} + +func signedBindingAt(t *testing.T, seq int64, supersedes *string, generation int64, zones ...binding.Zone) []byte { + t.Helper() + doc := binding.Binding{ + V: 1, BindingSeq: seq, DeviceID: "bench-01", IssuedAtMs: priorControlAt + 1, + SignerID: "commissioner", SigningKey: binding.SigningKeyName(revisionKey.Public().(ed25519.PublicKey)), + InventoryGeneration: generation, Supersedes: supersedes, Actor: "installer", Reason: "commissioned", + Zones: zones, + } + envelope, _, err := doc.SignedEnvelope(revisionKey) + if err != nil { + t.Fatalf("sign: %v", err) + } + return envelope +} + +func bindingInForce(t *testing.T, zones ...binding.Zone) *device { + t.Helper() + return bindingInForceAt(t, 1, zones...) +} + +func bindingInForceAt(t *testing.T, generation int64, zones ...binding.Zone) *device { + t.Helper() + envelope := signedBindingAt(t, 3, nil, generation, zones...) + accepted, err := binding.VerifyOffline(envelope) + if err != nil { + t.Fatalf("the binding in force does not verify: %v", err) + } + if !accepted.InForceEligible() { + t.Fatal("the fixture is not a binding that could be in force") + } + sensors := []any{} + actuators := []any{} + for _, z := range zones { + sensors = append(sensors, z.Sensor.SensorID) + actuators = append(actuators, map[string]any{ + "kind": "local_gpio", "identity": map[string]any{"gpio_pin": *z.Actuator.Identity.GPIOPin}, + }) + } + return &device{ + envelope: envelope, + accepted: accepted, + inv: map[string]any{ + "device_id": "bench-01", "sensor_ids": sensors, "actuators": actuators, + "deployment_posture": "development", "accepted_binding_seq": 3, + "accepted_binding_hash": accepted.CanonicalHash, + }, + } +} + +func singleZone(t *testing.T) *device { + return bindingInForce(t, provenZone("main", "load-current-main", 26, true)) +} + +func twoZones(t *testing.T) *device { + return bindingInForce(t, + provenZone("main", "load-current-main", 26, true), + provenZone("aux", "load-current-aux", 19, true)) +} + +// declaring replaces the actuators the device declares, by pin. +func (d *device) declaring(pins ...int) *device { + actuators := []any{} + for _, pin := range pins { + actuators = append(actuators, map[string]any{ + "kind": "local_gpio", "identity": map[string]any{"gpio_pin": pin}, + }) + } + d.inv["actuators"] = actuators + return d +} + +func (d *device) Run(_ context.Context, args ...string) (bridge.Result, error) { + d.calls = append(d.calls, append([]string(nil), args...)) + switch args[1] { + case "inventory": + body, _ := json.Marshal(map[string]any{"ok": true, "result": d.inv}) + return bridge.Result{Stdout: body}, nil + case "binding-export": + if d.export != "" { + return bridge.Result{Stdout: []byte(d.export)}, nil + } + body, _ := json.Marshal(map[string]any{"ok": true, "result": map[string]any{ + "binding_seq": 3, "binding_hash": d.accepted.CanonicalHash, + "envelope_json": string(d.envelope), + }}) + return bridge.Result{Stdout: body}, nil + } + return bridge.Result{}, fmt.Errorf("unexpected bridge call %v", args) +} + +func (d *device) exported() bool { + for _, call := range d.calls { + if call[1] == "binding-export" { + return true + } + } + return false +} + +// Answers for a revision, in the order the ceremony asks. Each fact is +// answered unchanged unless overridden. +type answers struct { + why, actuator, replaced, sensor, calibration, polarity, mapping, capacity, generation []string + proof []string +} + +func carry() answers { + return answers{ + why: []string{"breaker upgraded"}, actuator: []string{"unchanged"}, + replaced: []string{"none"}, sensor: []string{"unchanged"}, + calibration: []string{"unchanged"}, polarity: []string{"unchanged"}, + mapping: []string{"unchanged"}, capacity: []string{"unchanged"}, + generation: []string{"unchanged"}, + } +} + +// movedTo21 answers a zone moved to gpio_pin 21, which no zone drives. +func movedTo21() answers { + a := carry() + a.actuator = []string{"changed", "local_gpio (gpio_pin=21)"} + a.proof = freshProof(priorProofAt + 1) + return a +} + +// freshProof answers a pre_energisation leg for the mapping in the fixture. +func freshProof(at int64) []string { + return []string{ + binding.MethodPreEnergy, fmt.Sprint(at), + "energised", "open", "yes", "no", + "de_energised", "closed", "no", "yes", + } +} + +func (a answers) stdin() string { + var all []string + for _, part := range [][]string{ + a.why, a.actuator, a.replaced, a.sensor, a.calibration, a.polarity, a.mapping, + a.capacity, a.generation, a.proof, + } { + all = append(all, part...) + } + return strings.Join(all, "\n") + "\n" +} + +type runOpts struct { + json bool + zone string + // file, when set, is presented with --revise instead of the runtime's export. + file []byte +} + +type revisionRun struct { + code int + stdout, stderr string + out string +} + +// revise drives `ori binding capture` through the command tree. +func revise(t *testing.T, d *device, stdin string, opts runOpts) revisionRun { + t.Helper() + dir := t.TempDir() + out := filepath.Join(dir, "draft.json") + zone := opts.zone + if zone == "" { + zone = "main" + } + args := []string{"binding", "capture", "--path", "ori.yaml", "--zone", zone, "--out", out} + if opts.file != nil { + prior := filepath.Join(dir, "in-force.json") + if err := os.WriteFile(prior, opts.file, 0o600); err != nil { + t.Fatal(err) + } + args = append(args, "--revise", prior) + } + if opts.json { + args = append([]string{"--json"}, args...) + } + code, stdout, stderr := runWithOptions(args, Options{ + Bridge: d, + Stdin: strings.NewReader(stdin), + NowMs: func() int64 { return reviseNow }, + }) + return revisionRun{code: code, stdout: stdout, stderr: stderr, out: out} +} + +func (r revisionRun) draft(t *testing.T) binding.Binding { + t.Helper() + if r.code != 0 { + t.Fatalf("the revision exited %d:\n%s%s", r.code, r.stdout, r.stderr) + } + raw, err := os.ReadFile(r.out) + if err != nil { + t.Fatalf("no draft was written: %v", err) + } + doc, _, err := binding.DecodeDocument(raw) + if err != nil { + t.Fatalf("the draft does not decode: %v", err) + } + return doc +} + +// refused holds a refusal to its invariants: the exit status, the reason, and +// no draft on disk. In JSON mode, exactly one error object and nothing on stdout. +func (r revisionRun) refused(t *testing.T, name string, status int, because string, jsonMode bool) { + t.Helper() + if r.code != status { + t.Fatalf("%s: exit %d, want %d:\n%s%s", name, r.code, status, r.stdout, r.stderr) + } + if !jsonMode && !strings.Contains(r.stderr, because) { + t.Fatalf("%s: the refusal does not say %q:\n%s", name, because, r.stderr) + } + if _, err := os.Stat(r.out); !os.IsNotExist(err) { + t.Fatalf("%s: a refused capture wrote a draft", name) + } + if !jsonMode { + return + } + if strings.TrimSpace(r.stdout) != "" { + t.Fatalf("%s: a refusal wrote to stdout:\n%s", name, r.stdout) + } + // Prompts share stderr with the refusal; the refusal is the last thing on it. + idx := strings.LastIndex(r.stderr, "{\n \"ok\"") + if idx < 0 { + t.Fatalf("%s: no JSON refusal on stderr:\n%s", name, r.stderr) + } + decoder := json.NewDecoder(strings.NewReader(r.stderr[idx:])) + var payload map[string]any + if err := decoder.Decode(&payload); err != nil { + t.Fatalf("%s: the refusal is not a JSON object: %v", name, err) + } + if ok, _ := payload["ok"].(bool); ok { + t.Fatalf("%s: a refusal reported ok", name) + } + if msg, _ := payload["error"].(string); !strings.Contains(msg, because) { + t.Fatalf("%s: the JSON refusal does not say %q: %q", name, because, msg) + } + var extra any + if decoder.Decode(&extra) == nil { + t.Fatalf("%s: more than one JSON object after the refusal", name) + } +} + +func bothModes(t *testing.T, each func(t *testing.T, jsonMode bool)) { + for _, jsonMode := range []bool{false, true} { + each(t, jsonMode) + } +} + +// deliverable signs the draft as sign would and runs it through every stage a +// runtime holding the binding in force would, with the zone state it retained +// and the hardware the device declares. +func deliverable( + t *testing.T, d *device, draft binding.Binding, multiplier *float64, +) (*binding.Accepted, error) { + t.Helper() + draft.IssuedAtMs, draft.SignerID, draft.Actor = reviseNow, "commissioner", "installer" + draft.SigningKey = binding.SigningKeyName(revisionKey.Public().(ed25519.PublicKey)) + envelope, _, err := draft.SignedEnvelope(revisionKey) + if err != nil { + return nil, err + } + raw, _ := json.Marshal(d.inv) + var inv capture.Inventory + if err := json.Unmarshal(raw, &inv); err != nil { + t.Fatal(err) + } + refs, err := capture.DeclaredRefs(inv) + if err != nil { + t.Fatal(err) + } + hash := d.accepted.CanonicalHash + return binding.VerifyEnvelope(envelope, binding.Context{ + DeviceID: "bench-01", + CommissioningAnchorCurrent: revisionKey.Public().(ed25519.PublicKey), + AcceptedBindingSeq: 3, + AcceptedBindingHash: &hash, + DeclaredSensorIDs: inv.SensorIDs, + DeclaredActuators: refs, + DeploymentPosture: "development", + ProfileMultiplier: multiplier, + AcceptedZoneState: binding.RetainedState(d.accepted), + }) +} + +type revisionJSON struct { + OK bool `json:"ok"` + Result struct { + Path string `json:"path"` + Revision capture.Revision `json:"revision"` + } `json:"result"` +} + +func (r revisionRun) revision(t *testing.T) capture.Revision { + t.Helper() + var payload revisionJSON + if err := json.Unmarshal([]byte(r.stdout), &payload); err != nil || !payload.OK { + t.Fatalf("the JSON output is not one ok object: %v\n%s", err, r.stdout) + } + if payload.Result.Path != r.out { + t.Fatalf("the JSON output names %q, not the draft written", payload.Result.Path) + } + return payload.Result.Revision +} + +func TestRevisionNamesTheBindingInForce(t *testing.T) { + a := carry() + a.capacity = []string{"changed", "installer_measured", "16"} + for _, route := range []string{"export", "file"} { + d := singleZone(t) + opts := runOpts{} + if route == "file" { + opts.file = d.envelope + } + draft := revise(t, d, a.stdin(), opts).draft(t) + if draft.BindingSeq != 4 { + t.Fatalf("%s: binding_seq %d, want one past the 3 in force", route, draft.BindingSeq) + } + if draft.Supersedes == nil || *draft.Supersedes != d.accepted.CanonicalHash { + t.Fatalf("%s: supersedes %v, want %s", route, draft.Supersedes, d.accepted.CanonicalHash) + } + if (route == "export") != d.exported() { + t.Fatalf("%s: the binding in force was read from the wrong place: %v", route, d.calls) + } + accepted, err := deliverable(t, d, draft, nil) + if err != nil { + t.Fatalf("%s: a runtime holding the binding in force refuses the revision: %v", route, err) + } + if !accepted.InForceEligible() { + t.Fatalf("%s: a capacity-only revision lost the proof it carries", route) + } + } +} + +// The prior value of everything changed is carried into the reason, after the +// installer's own why. +func TestRevisionCarriesPriorValuesIntoTheReason(t *testing.T) { + a := movedTo21() + a.why = []string{"contactor moved to the new panel"} + a.replaced = []string{"sensor"} + a.capacity = []string{"changed", "nameplate", "16"} + a.generation = []string{"changed", "2"} + draft := revise(t, singleZone(t).declaring(21), a.stdin(), runOpts{}).draft(t) + for _, want := range []string{ + "contactor moved to the new panel. ", + "actuator was local_gpio (gpio_pin=26), now local_gpio (gpio_pin=21)", + "replaced_like_for_like was as commissioned, now sensor replaced", + "rated_capacity was 10A (nameplate), now 16A (nameplate)", + "inventory_generation was 1, now 2", + } { + if !strings.Contains(draft.Reason, want) { + t.Fatalf("the reason does not carry %q:\n%s", want, draft.Reason) + } + } +} + +// The signer's reason is the one capture composed. sign keeps it and refuses a +// --reason that would replace it, rather than discarding either. +func TestSignKeepsTheCarriedReason(t *testing.T) { + a := carry() + a.capacity = []string{"changed", "nameplate", "16"} + run := revise(t, singleZone(t), a.stdin(), runOpts{}) + draft := run.draft(t) + dir := filepath.Dir(run.out) + key := writeTemp(t, dir, "key", []byte(fmt.Sprintf("%x", revisionKey.Seed())), 0o600) + + signed := filepath.Join(dir, "signed.json") + code, _, stderr := runWithOptions([]string{"binding", "sign", "--in", run.out, "--key", key, + "--signer-id", "s", "--actor", "a", "--out", signed}, Options{}) + if code != 0 { + t.Fatalf("sign refused the revision draft: %s", stderr) + } + accepted, err := binding.VerifyOffline(mustRead(t, signed)) + if err != nil { + t.Fatal(err) + } + var env struct { + Binding struct { + Reason string `json:"reason"` + } `json:"binding"` + } + _ = json.Unmarshal(accepted.CanonicalBytes, &env.Binding) + if env.Binding.Reason != draft.Reason { + t.Fatalf("the signed reason %q is not the one capture carried %q", env.Binding.Reason, draft.Reason) + } + + other := filepath.Join(dir, "other.json") + code, _, stderr = runWithOptions([]string{"binding", "sign", "--in", run.out, "--key", key, + "--signer-id", "s", "--actor", "a", "--reason", "something else", "--out", other}, Options{}) + if code != 2 || !strings.Contains(stderr, "signing does not rewrite a document") { + t.Fatalf("a --reason replacing the carried one was not refused: exit %d %s", code, stderr) + } + mustNotExist(t, other) +} + +func mustRead(t *testing.T, path string) []byte { + t.Helper() + raw, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + return raw +} + +// Only the binding the runtime reports in force is a prior, whichever route +// presents it; anything else is refused before a question is asked. +func TestRevisionRefusesAnythingButTheBindingInForce(t *testing.T) { + ok := func(d *device, result map[string]any) string { + body, _ := json.Marshal(map[string]any{"ok": true, "result": result}) + return string(body) + } + provisional := func(d *device) []byte { + hash := d.accepted.CanonicalHash + return signedBinding(t, 4, &hash, provenZone("main", "load-current-main", 26, false)) + } + cases := []struct { + name string + setup func(d *device) runOpts + because string + }{ + {"export refuses", func(d *device) runOpts { + d.export = `{"ok":false,"command":"commissioning binding-export",` + + `"error":{"code":"no_binding_in_force","detail":"this device holds no binding in force"}}` + return runOpts{} + }, "no_binding_in_force"}, + {"export names another hash", func(d *device) runOpts { + d.export = ok(d, map[string]any{"binding_seq": 3, "binding_hash": "sha256:" + strings.Repeat("0", 64), + "envelope_json": string(d.envelope)}) + return runOpts{} + }, "the runtime exported binding"}, + {"export names another sequence", func(d *device) runOpts { + d.export = ok(d, map[string]any{"binding_seq": 2, "binding_hash": d.accepted.CanonicalHash, + "envelope_json": string(d.envelope)}) + return runOpts{} + }, "the runtime exported binding"}, + {"export carries no envelope", func(d *device) runOpts { + d.export = ok(d, map[string]any{"binding_seq": 3, "binding_hash": d.accepted.CanonicalHash}) + return runOpts{} + }, "carries no envelope"}, + {"export envelope as an object", func(d *device) runOpts { + d.export = ok(d, map[string]any{"binding_seq": 3, "binding_hash": d.accepted.CanonicalHash, + "envelope_json": json.RawMessage(d.envelope)}) + return runOpts{} + }, "not readable"}, + {"export envelope truncated", func(d *device) runOpts { + d.export = ok(d, map[string]any{"binding_seq": 3, "binding_hash": d.accepted.CanonicalHash, + "envelope_json": string(d.envelope[:len(d.envelope)/2])}) + return runOpts{} + }, "does not verify"}, + {"export of the provisional document", func(d *device) runOpts { + d.export = ok(d, map[string]any{"binding_seq": 3, "binding_hash": d.accepted.CanonicalHash, + "envelope_json": string(provisional(d))}) + return runOpts{} + }, "the binding in force on device"}, + {"file of the provisional document", func(d *device) runOpts { + return runOpts{file: provisional(d)} + }, "the binding in force on device"}, + {"file of another document", func(d *device) runOpts { + return runOpts{file: signedBinding(t, 3, nil, provenZone("main", "load-current-main", 26, false))} + }, "the binding in force on device"}, + {"file with an unknown field", func(d *device) runOpts { + return runOpts{file: []byte(strings.Replace(string(d.envelope), `{"binding":{`, `{"binding":{"extra":1,`, 1))} + }, "does not verify"}, + {"file with no binding in force", func(d *device) runOpts { + d.inv["accepted_binding_seq"], d.inv["accepted_binding_hash"] = 0, nil + return runOpts{file: d.envelope} + }, "no binding in force"}, + } + for _, tc := range cases { + bothModes(t, func(t *testing.T, jsonMode bool) { + d := singleZone(t) + opts := tc.setup(d) + opts.json = jsonMode + run := revise(t, d, carry().stdin(), opts) + run.refused(t, tc.name, 2, tc.because, jsonMode) + if strings.Contains(run.stderr, "Actuator:") { + t.Fatalf("%s: a question was asked before the refusal", tc.name) + } + }) + } +} + +// The inventory's account of the binding in force and the document must agree +// on its sequence and device, not only its hash. +func TestRevisionRefusesAnInventoryThatMisdescribesThePrior(t *testing.T) { + for name, tweak := range map[string]func(d *device){ + "another sequence": func(d *device) { d.inv["accepted_binding_seq"] = 7 }, + "another device": func(d *device) { d.inv["device_id"] = "bench-02" }, + } { + bothModes(t, func(t *testing.T, jsonMode bool) { + d := singleZone(t) + tweak(d) + run := revise(t, d, carry().stdin(), runOpts{file: d.envelope, json: jsonMode}) + run.refused(t, name, 2, "the inventory does not describe it", jsonMode) + }) + } +} + +// A sequence without a hash, or the reverse, is not a device state, and a +// producer that chose one would chain onto a document the device never held. +func TestCaptureRefusesAChainThatContradictsItself(t *testing.T) { + for name, tweak := range map[string]func(d *device){ + "sequence without hash": func(d *device) { d.inv["accepted_binding_hash"] = nil }, + "hash without sequence": func(d *device) { d.inv["accepted_binding_seq"] = 0 }, + "hash not canonical": func(d *device) { d.inv["accepted_binding_hash"] = "sha256:XYZ" }, + } { + bothModes(t, func(t *testing.T, jsonMode bool) { + d := singleZone(t) + tweak(d) + run := revise(t, d, captureAnswers, runOpts{json: jsonMode}) + run.refused(t, name, 1, "the runtime inventory reports", jsonMode) + }) + } +} + +// With a binding in force there is no capture without a prior: capture reads +// it from the runtime, and a device that cannot export it gets nothing. +func TestCaptureOnABindingInForceIsARevision(t *testing.T) { + bothModes(t, func(t *testing.T, jsonMode bool) { + d := singleZone(t) + d.export = `{"ok":false,"error":{"code":"retained_binding_mismatch","detail":"nothing is exported"}}` + run := revise(t, d, captureAnswers, runOpts{json: jsonMode}) + run.refused(t, "export unavailable", 2, "retained_binding_mismatch", jsonMode) + if !d.exported() { + t.Fatal("capture on a device with a binding in force did not read it") + } + }) +} + +func TestRevisionCarriesWhatDidNotChange(t *testing.T) { + d := twoZones(t) + a := carry() + a.capacity = []string{"changed", "design_document", "12.5"} + run := revise(t, d, a.stdin(), runOpts{}) + draft := run.draft(t) + + for _, question := range []string{ + "Full-scale range", "Below what change", "To OPEN the protected circuit", + "How was the circuit leg established", "Commanding", + } { + if strings.Contains(run.stderr, question) { + t.Fatalf("a carried fact was asked again (%q):\n%s", question, run.stderr) + } + } + priorDoc := decodeEnvelope(t, d.envelope) + if len(draft.Zones) != 2 { + t.Fatalf("the revision has %d zones, want both in force", len(draft.Zones)) + } + for i, z := range draft.Zones { + want := priorDoc.Zones[i] + if z.ZoneID == "main" { + if z.RatedCapacity.Value != 12.5 || z.RatedCapacity.Provenance != "design_document" { + t.Fatalf("the changed capacity was not recorded: %+v", z.RatedCapacity) + } + want.RatedCapacity = z.RatedCapacity + } + // Carried means the same canonical bytes, proof legs and all. + if zoneBytes(t, z) != zoneBytes(t, want) { + t.Fatalf("zone %q was not carried as it is in force:\n got %s\nwant %s", + z.ZoneID, zoneBytes(t, z), zoneBytes(t, want)) + } + } + if draft.InventoryGeneration != priorDoc.InventoryGeneration { + t.Fatal("the inventory generation was not carried") + } + accepted, err := deliverable(t, d, draft, nil) + if err != nil { + t.Fatalf("a runtime holding the binding in force refuses the revision: %v", err) + } + if !accepted.InForceEligible() { + t.Fatal("a revision that carried both legs is not in force") + } +} + +// Fresh legs on a line the binding in force still drives can never be proven, +// so the change is refused by name the moment it is declared: no proof is +// asked for, and no one is told to go and prove it. +func TestRevisionRefusesFreshLegsOnADrivenLine(t *testing.T) { + cases := []struct { + name string + device func(*testing.T) *device + answer func(*answers) + fact string + owner string + pin int + }{ + {"polarity flipped", singleZone, func(a *answers) { a.polarity = []string{"changed", "low"} }, + "active_high", "main", 26}, + {"recalibrated", singleZone, func(a *answers) { a.calibration = []string{"changed", "cal-2"} }, + "calibration_ref", "main", 26}, + {"mapping rewired", singleZone, func(a *answers) { + a.mapping = []string{"changed", "de_energised", "energised", "open"} + }, "commissioned_mapping", "main", 26}, + {"sensor re-described", singleZone, func(a *answers) { + a.sensor = []string{"changed", "load-current-main", "current", "ampere", + "positive_is_load_draw", "0", "50", "0.05", "cal-main"} + a.calibration = nil + }, "sensor", "main", 26}, + {"relay replaced like for like", singleZone, func(a *answers) { + a.replaced = []string{"relay or contactor"} + }, "replaced_like_for_like", "main", 26}, + {"clamp replaced like for like", singleZone, func(a *answers) { + a.replaced = []string{"sensor"} + }, "replaced_like_for_like", "main", 26}, + {"moved onto another zone's line", twoZones, func(a *answers) { + a.actuator = []string{"changed", "local_gpio (gpio_pin=19)"} + }, "actuator", "aux", 19}, + } + for _, tc := range cases { + bothModes(t, func(t *testing.T, jsonMode bool) { + a := carry() + tc.answer(&a) + a.proof = freshProof(priorProofAt + 1) + run := revise(t, tc.device(t), a.stdin(), runOpts{json: jsonMode}) + run.refused(t, tc.name, 2, fmt.Sprintf( + "%s changed, so zone \"main\" needs fresh legs, and gpio_pin=%d is still driven by zone %q", + tc.fact, tc.pin, tc.owner), jsonMode) + for _, never := range []string{"How was the circuit leg established", "prove both outcomes"} { + if strings.Contains(run.stderr, never) { + t.Fatalf("%s: %q reached the installer for a line that cannot be proven:\n%s", + tc.name, never, run.stderr) + } + } + // Refused as declared: nothing after the declaring answer is asked. + if tc.fact == "replaced_like_for_like" && strings.Contains(run.stderr, "Sensor:") { + t.Fatalf("%s: the ceremony went on past the change that decided it", tc.name) + } + }) + } +} + +// A changed zone moved to a line no zone drives is captured with fresh legs, +// named before they are asked for, and the control leg in force is not carried. +func TestRevisionRequiresFreshProof(t *testing.T) { + cases := []struct { + name string + answer func(*answers) + facts []string + }{ + {"moved", func(*answers) {}, []string{"actuator"}}, + {"moved and flipped", func(a *answers) { a.polarity = []string{"changed", "low"} }, + []string{"actuator", "active_high"}}, + {"moved and recalibrated", func(a *answers) { a.calibration = []string{"changed", "cal-2"} }, + []string{"actuator", "calibration_ref"}}, + {"moved with its relay replaced", func(a *answers) { a.replaced = []string{"relay or contactor"} }, + []string{"actuator", "replaced_like_for_like"}}, + {"moved and rewired", func(a *answers) { + a.mapping = []string{"changed", "de_energised", "energised", "open"} + a.proof = []string{binding.MethodPreEnergy, fmt.Sprint(priorProofAt + 1), + "de_energised", "open", "yes", "no", "energised", "closed", "no", "yes"} + }, []string{"actuator", "commissioned_mapping"}}, + } + for _, tc := range cases { + bothModes(t, func(t *testing.T, jsonMode bool) { + d := singleZone(t).declaring(21) + a := movedTo21() + tc.answer(&a) + run := revise(t, d, a.stdin(), runOpts{json: jsonMode}) + draft := run.draft(t) + + stated := strings.Index(run.stderr, fmt.Sprintf("needs a fresh circuit leg performed after %d", priorProofAt)) + asked := strings.LastIndex(run.stderr, "How was the circuit leg established") + if stated < 0 || asked < 0 || stated > asked { + t.Fatalf("%s: the fresh proof was not named before it was asked for:\n%s", tc.name, run.stderr) + } + zone := draft.Zones[0] + if zone.Proof.ControlPath != nil { + t.Fatalf("%s: the control leg in force was carried onto a changed zone", tc.name) + } + if _, err := deliverable(t, d, draft, nil); err != nil { + t.Fatalf("%s: the runtime refuses the revision: %v", tc.name, err) + } + stale := draft + stale.Zones = append([]binding.Zone(nil), draft.Zones...) + stale.Zones[0].Proof.PerformedAtMs = priorProofAt + if _, err := deliverable(t, d, stale, nil); err == nil || + !strings.Contains(err.Error(), binding.ReasonStaleProof) { + t.Fatalf("%s: the circuit leg in force was not stale: %v", tc.name, err) + } + if jsonMode { + rev := run.revision(t) + if !rev.FreshProof || strings.Join(rev.Because, ",") != strings.Join(tc.facts, ",") || + rev.ControlLeg != "prove_after_delivery" || rev.ProofState != capture.StateProvisional || + rev.CircuitLegAfterMs != priorProofAt { + t.Fatalf("%s: the JSON revision does not say what is required: %s", tc.name, run.stdout) + } + } + }) + } +} + +// A leg time no later than the proof in force is refused as it is entered, +// before the observations are asked; so is one dated past this machine's clock. +func TestRevisionRefusesALegTimeAsItIsEntered(t *testing.T) { + cases := map[int64]string{ + priorProofAt: "is not after the proof in force", + priorProofAt - 1: "is not after the proof in force", + reviseNow + 5*60*1000 + 1: "later than this machine's clock", + reviseNow + 1000*365*86400000: "later than this machine's clock", + } + for at, because := range cases { + bothModes(t, func(t *testing.T, jsonMode bool) { + a := movedTo21() + a.proof = freshProof(at) + run := revise(t, singleZone(t).declaring(21), a.stdin(), runOpts{json: jsonMode}) + run.refused(t, fmt.Sprint(at), 2, because, jsonMode) + if strings.Contains(run.stderr, "Commanding") { + t.Fatalf("%d: the observations were asked after a leg time that could not stand", at) + } + }) + } + a := movedTo21() + a.proof = freshProof(reviseNow + 5*60*1000) + revise(t, singleZone(t).declaring(21), a.stdin(), runOpts{}).draft(t) +} + +// The first-capture ceremony refuses a future-dated proof as well: it is the +// time every later revision has to follow. +func TestCaptureRefusesAFutureProof(t *testing.T) { + future := strings.Replace(captureAnswers, "pre_energisation\n1800000000000\n", + "pre_energisation\n25080000000000\n", 1) + d := &device{inv: map[string]any{ + "device_id": "bench-01", "sensor_ids": []any{"load-current-main"}, + "actuators": []any{map[string]any{"kind": "local_gpio", "identity": map[string]any{"gpio_pin": 26}}}, + "deployment_posture": "development", "accepted_binding_seq": 0, "accepted_binding_hash": nil, + }} + run := revise(t, d, future, runOpts{}) + run.refused(t, "future first proof", 2, "later than this machine's clock", false) +} + +// Proven, provisional and undemonstrated are three things; the trip-point bound +// is deferred to delivery in every one of them, and never reported as checked. +func TestRevisionReportsThreeProofStates(t *testing.T) { + carried := carry() + carried.capacity = []string{"changed", "nameplate", "11"} + unproven := movedTo21() + unproven.proof = []string{binding.MethodUnproven, "the load could not be isolated"} + for want, a := range map[string]answers{ + capture.StateProven: carried, capture.StateProvisional: movedTo21(), + capture.StateUndemonstrated: unproven, + } { + device := func() *device { + if want == capture.StateProven { + return singleZone(t) + } + return singleZone(t).declaring(21) + } + got := revise(t, device(), a.stdin(), runOpts{json: true}).revision(t) + if got.ProofState != want || got.TripPointBound != "deferred_to_delivery" { + t.Fatalf("reported %q / %q, want %q / deferred_to_delivery", got.ProofState, got.TripPointBound, want) + } + text := revise(t, device(), a.stdin(), runOpts{}) + if !strings.Contains(text.stderr, fmt.Sprintf("proof once delivered: %s\n", want)) || + !strings.Contains(text.stderr, "not checked here, decided at delivery") { + t.Fatalf("the text report does not say %q with the bound deferred:\n%s", want, text.stderr) + } + } +} + +// A capacity above full scale over the release's multiplier passes every check +// capture can make and fails the trip-point bound at delivery; the report says +// that bound was not checked rather than calling the zone ready. +func TestRevisionDefersTheTripPointBound(t *testing.T) { + a := carry() + a.capacity = []string{"changed", "nameplate", "60"} + bothModes(t, func(t *testing.T, jsonMode bool) { + d := singleZone(t) + run := revise(t, d, a.stdin(), runOpts{json: jsonMode}) + draft := run.draft(t) + if jsonMode { + if rev := run.revision(t); rev.TripPointBound != "deferred_to_delivery" { + t.Fatalf("the trip-point bound is reported %q", rev.TripPointBound) + } + } else if !strings.Contains(run.stderr, "trip-point bound") || + !strings.Contains(run.stderr, "not checked here, decided at delivery") { + t.Fatalf("the text report does not defer the trip-point bound:\n%s", run.stderr) + } + two := 2.0 + if _, err := deliverable(t, d, draft, &two); err == nil || + !strings.Contains(err.Error(), binding.ReasonOutOfBounds) { + t.Fatalf("a 60A capacity on a 100A sensor passed a x2 trip-point bound: %v", err) + } + }) +} + +// Every other way a revision can go wrong at the panel is refused with nothing +// written, in text and in JSON. +func TestRevisionRefusals(t *testing.T) { + cases := []struct { + name string + device func(*testing.T) *device + answers func() answers + zone string + because string + }{ + {"a sensor moved onto another zone's", func(t *testing.T) *device { return twoZones(t).declaring(19, 21) }, + func() answers { + a := movedTo21() + a.sensor = []string{"changed", "load-current-aux"} + a.calibration = nil + return a + }, "main", "is bound to zone \"aux\""}, + {"a capacity the sensor cannot observe", singleZone, func() answers { + a := carry() + a.capacity = []string{"changed", "nameplate", "150"} + return a + }, "main", "full scale"}, + {"polarity answered changed to the value in force", func(t *testing.T) *device { + return singleZone(t).declaring(21) + }, func() answers { + a := movedTo21() + a.polarity = []string{"changed", "high"} + return a + }, "main", "answered changed and then given the value in force"}, + {"a zone not in force", singleZone, carry, "elsewhere", "has no zone"}, + {"no reason given", singleZone, func() answers { + a := carry() + a.why = []string{""} + return a + }, "main", "records why it was made"}, + {"input ending mid-ceremony", singleZone, func() answers { + return answers{why: []string{"w"}, actuator: []string{"unchanged"}} + }, "main", "the ceremony ended"}, + {"no input at all", singleZone, func() answers { return answers{} }, "main", "the ceremony ended"}, + {"a mapping that contradicts itself", func(t *testing.T) *device { return singleZone(t).declaring(21) }, + func() answers { + a := movedTo21() + a.mapping = []string{"changed", "de_energised", "energised", "closed"} + return a + }, "main", "one of those two observations"}, + // Every earlier check passes; only the gate that runs the verifier's + // own stages over the draft sees the pin the move left unbound. + {"a move that leaves a declared pin unbound", func(t *testing.T) *device { + return singleZone(t).declaring(19, 21, 26) + }, movedTo21, "main", "the runtime would refuse this revision (inventory: unbound_actuator)"}, + {"a claimed leg against a proof in force dated just ahead", func(t *testing.T) *device { + return bindingInForce(t, zoneProvenAt(reviseNow+60*1000)).declaring(21) + }, func() answers { + a := movedTo21() + a.proof = freshProof(reviseNow + 30*1000) + return a + }, "main", "the proof in force is dated 1800000060000, after this machine's clock"}, + {"fresh legs against a proof in force dated far ahead", func(t *testing.T) *device { + return bindingInForce(t, zoneProvenAt(reviseNow+10*86400000)).declaring(21) + }, movedTo21, "main", "the proof in force is dated 1800864000000, after this machine's clock"}, + // The boundary: a proof in force dated exactly at the clock plus the + // skew leaves no instant a fresh leg could be dated. + {"fresh legs against a proof in force dated at the skew (far ahead boundary)", func(t *testing.T) *device { + return bindingInForce(t, zoneProvenAt(reviseNow+5*60*1000)).declaring(21) + }, movedTo21, "main", "the proof in force is dated 1800000300000, after this machine's clock"}, + {"a lower inventory generation", func(t *testing.T) *device { + return bindingInForceAt(t, 5, provenZone("main", "load-current-main", 26, true)) + }, func() answers { + a := carry() + a.generation = []string{"changed", "4"} + return a + }, "main", "inventory generation 4 is below the 5"}, + } + for _, tc := range cases { + bothModes(t, func(t *testing.T, jsonMode bool) { + stdin := tc.answers().stdin() + if tc.name == "no input at all" { + stdin = "" + } + run := revise(t, tc.device(t), stdin, runOpts{json: jsonMode, zone: tc.zone}) + run.refused(t, tc.name, 2, tc.because, jsonMode) + if strings.Contains(tc.name, "far ahead") && + strings.Contains(run.stderr, "When was that proof performed") { + t.Fatalf("%s: a proof was asked for that no time could satisfy", tc.name) + } + }) + } +} + +// zoneProvenAt is the fixture zone with both legs dated from at. +func zoneProvenAt(at int64) binding.Zone { + z := provenZone("main", "load-current-main", 26, true) + z.Proof.PerformedAtMs = at + leg := *z.Proof.ControlPath + leg.PerformedAtMs = at + 1 + z.Proof.ControlPath = &leg + return z +} + +// An undemonstrated leg claims no proof, so it is not held to the time of the +// proof in force, even one dated ahead of this machine's clock: the zone is +// captured, and delivered, as undemonstrated. +func TestAnUnclaimedLegIsNotHeldToTheRetainedTime(t *testing.T) { + for _, priorAt := range []int64{reviseNow + 60*1000, reviseNow + 5*60*1000, reviseNow + 10*86400000} { + bothModes(t, func(t *testing.T, jsonMode bool) { + d := bindingInForce(t, zoneProvenAt(priorAt)).declaring(21) + a := movedTo21() + a.proof = []string{binding.MethodUnproven, "the load could not be isolated"} + run := revise(t, d, a.stdin(), runOpts{json: jsonMode}) + draft := run.draft(t) + // A circuit leg not redone is recorded undemonstrated; a control + // leg not redone is left absent, never written undemonstrated. + if draft.Zones[0].Proof.Method != binding.MethodUnproven { + t.Fatalf("%d: the leg was not recorded undemonstrated", priorAt) + } + if draft.Zones[0].Proof.ControlPath != nil { + t.Fatalf("%d: a control leg that was not redone was written", priorAt) + } + if jsonMode { + if rev := run.revision(t); rev.ProofState != capture.StateUndemonstrated { + t.Fatalf("%d: reported %q", priorAt, rev.ProofState) + } + } + accepted, err := deliverable(t, d, draft, nil) + if err != nil || accepted.InForceEligible() { + t.Fatalf("%d: an unclaimed leg was refused, or reached in force: %v", priorAt, err) + } + }) + } +} + +func decodeEnvelope(t *testing.T, envelope []byte) binding.Binding { + t.Helper() + var env struct { + Binding json.RawMessage `json:"binding"` + } + if err := json.Unmarshal(envelope, &env); err != nil { + t.Fatal(err) + } + doc, _, err := binding.DecodeDocument(env.Binding) + if err != nil { + t.Fatal(err) + } + return doc +} + +// zoneBytes is a zone's canonical form, compared as the signature would see it. +func zoneBytes(t *testing.T, z binding.Zone) string { + t.Helper() + doc := binding.Binding{ + V: 1, BindingSeq: 1, DeviceID: "d", SignerID: "s", Actor: "a", Reason: "r", + SigningKey: binding.SigningKeyName(revisionKey.Public().(ed25519.PublicKey)), + InventoryGeneration: 1, Zones: []binding.Zone{z}, + } + pre, err := doc.Preimage() + if err != nil { + t.Fatal(err) + } + return string(pre) +} + +// The revision rule follows the hardware, not the name: every retained zone a +// revised zone shares a name, a pin or a sensor with holds it to fresh legs. +func TestTheRevisionRuleFollowsTheHardwareNotTheName(t *testing.T) { + d := twoZones(t) + prior := decodeEnvelope(t, d.envelope) + revision := func(edit func(zones []binding.Zone)) binding.Binding { + zones := make([]binding.Zone, len(prior.Zones)) + copy(zones, prior.Zones) + edit(zones) + hash := d.accepted.CanonicalHash + return binding.Binding{V: 1, BindingSeq: 4, DeviceID: "bench-01", + InventoryGeneration: 1, Supersedes: &hash, Reason: "r", Zones: zones} + } + circuitOnly := func(z *binding.Zone) { z.Proof.ControlPath = nil } + cases := []struct { + name string + edit func([]binding.Zone) + stale bool + }{ + {"renamed, nothing else", func(z []binding.Zone) { z[0].ZoneID = "main-renamed" }, false}, + {"renamed and flipped", func(z []binding.Zone) { + z[0].ZoneID = "main-renamed" + z[0].Actuator.Identity.ActiveHigh = boolPtr(false) + circuitOnly(&z[0]) + }, true}, + {"renamed and sensor re-described", func(z []binding.Zone) { + z[0].ZoneID = "main-renamed" + z[0].Sensor.RangeMax = 50 + }, true}, + // Each of these shares exactly one thing with a retained zone. + {"renamed onto main's pin with another sensor, flipped", func(z []binding.Zone) { + z[0].ZoneID = "x" + z[0].Sensor.SensorID = "load-current-spare" + z[0].Actuator.Identity.ActiveHigh = boolPtr(false) + circuitOnly(&z[0]) + }, true}, + {"renamed onto main's sensor on another pin, re-described", func(z []binding.Zone) { + z[0].ZoneID = "y" + z[0].Actuator.Identity.GPIOPin = intPtr(21) + z[0].Sensor.RangeMax = 50 + }, true}, + {"moved to a new pin and a new sensor, keeping only its name", func(z []binding.Zone) { + z[0].Actuator.Identity.GPIOPin = intPtr(21) + z[0].Sensor.SensorID = "load-current-spare" + }, true}, + {"mapping rewired, nothing else", func(z []binding.Zone) { + z[0].Actuator.Mapping = binding.Mapping{ + OpenProtectedCircuit: binding.CoilDeEnergised, CloseProtectedCircuit: binding.CoilEnergised, + DeEnergisedTerminalState: binding.CircuitOpen, + } + // The circuit leg observes the new mapping but keeps the time of + // the proof in force, so only its age is wrong. + z[0].Proof.Observations = append([]binding.Observation(nil), z[0].Proof.Observations...) + for i := range z[0].Proof.Observations { + o := &z[0].Proof.Observations[i] + o.CoilState = map[string]string{ + binding.OutcomeOpen: binding.CoilDeEnergised, binding.OutcomeClose: binding.CoilEnergised, + }[o.Commanded] + } + circuitOnly(&z[0]) + }, true}, + {"two zones exchanging sensors", func(z []binding.Zone) { + z[0].Sensor, z[1].Sensor = z[1].Sensor, z[0].Sensor + }, true}, + {"main onto aux's pin while aux moves away", func(z []binding.Zone) { + z[0].Actuator.Identity.GPIOPin = intPtr(19) + z[1].Actuator.Identity.GPIOPin = intPtr(21) + circuitOnly(&z[0]) + circuitOnly(&z[1]) + }, true}, + } + for _, tc := range cases { + draft := revision(tc.edit) + // The device declares exactly what the revision binds, so nothing but + // the revision rule stands between it and acceptance. + var pins []int + var sensors []any + for _, z := range draft.Zones { + pins = append(pins, *z.Actuator.Identity.GPIOPin) + sensors = append(sensors, z.Sensor.SensorID) + } + d.inv["sensor_ids"] = sensors + accepted, err := deliverable(t, d.declaring(pins...), draft, nil) + if tc.stale { + if err == nil || !strings.Contains(err.Error(), binding.ReasonStaleProof) { + t.Fatalf("%s: verdict %v, want stale_proof", tc.name, err) + } + continue + } + if err != nil || !accepted.InForceEligible() { + t.Fatalf("%s: a rename that changed nothing was refused or lost its proof: %v", tc.name, err) + } + } +} diff --git a/cmd/binding_test.go b/cmd/binding_test.go index 9f3b77a..550b12c 100644 --- a/cmd/binding_test.go +++ b/cmd/binding_test.go @@ -164,7 +164,7 @@ func stateWith(bridge BridgeRunner, stdout, stderr *bytes.Buffer) *rootState { const inventoryOK = `{"ok":true,"result":{"device_id":"bench-01", "sensor_ids":["load-current-main"], "actuators":[{"kind":"local_gpio","identity":{"gpio_pin":26}}], -"deployment_posture":"development","accepted_binding_seq":3}}` +"deployment_posture":"development","accepted_binding_seq":0,"accepted_binding_hash":null}}` // sensor, actuator, polarity, open, close, terminal, capacity, range, method const exportBothMatched = `{"ok":true,"result":{"observations":[ diff --git a/cmd/root.go b/cmd/root.go index 4998f06..83ebf96 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -34,6 +34,8 @@ type Options struct { UseToken func(string, token.UseOptions) (token.OfflineUseResult, error) FirmwareMQTT FirmwareMQTTRunner NowMs func() int64 + // Stdin is what interactive commands read; os.Stdin when nil. + Stdin io.Reader } type rootState struct { @@ -81,6 +83,9 @@ func ExecuteWithOptions(args []string, stdout io.Writer, stderr io.Writer, opts root := newRootCommand(&state) root.SetArgs(args) + if opts.Stdin != nil { + root.SetIn(opts.Stdin) + } root.SetOut(stdout) root.SetErr(stderr) if err := root.Execute(); err != nil { diff --git a/internal/binding/export_test.go b/internal/binding/export_test.go new file mode 100644 index 0000000..2de824f --- /dev/null +++ b/internal/binding/export_test.go @@ -0,0 +1,516 @@ +// Copyright 2026 Ori Nexus Systems LTD +// SPDX-License-Identifier: Apache-2.0 + +package binding + +import ( + "sort" + "strings" +) + +// RevisionRule is one reading of the revision rule, switch by switch, so a +// test can hold the corpus to readings other than the verifier's own. The +// switches and their values mirror the runtime's mutation-adequacy harness. +type RevisionRule struct { + MatchName bool + MatchActuator bool + MatchSensor bool + SensorMatch string // sensor_id | whole | id_and: + GPIOMatch string // pin | whole + FirmwareMatch string // identity | board | channel + + ChangeIdentity bool + IdentityCompare string // whole | ignore_board | ignore_channel + ChangeMapping bool + // whole | sensor_id | id_and_calibration | ignore:, where range + // names range_min and range_max together + ChangeSensor string + RenameIsChange bool + + // all | first | last | latest_proof | sensor_first | name_if_no_actuator | + // break_on_unchanged | stop_after_pass + Visit string + + CircuitUnclaimedExempt bool + CircuitSkipIfControlFresh bool + CircuitOnlySingleMatch bool + CircuitStrict bool + ControlRequiresClaim bool + ControlOn string // any_change | identity | identity_or_mapping + ControlSkipIfCircuitUnclaimed bool + ControlMissing string // fresh | stale | circuit_time + ControlStrict bool + + OneToOne bool + ControlOnlySingleMatch bool + CircuitSkipIfControlUnclaimed bool + ControlAbsentStale bool + SingleRetainedTime bool + FreshAgainstEveryMatchOnceChanged bool + ProofChangeIsChange bool + ClaimedMethods string // any_but_undemonstrated | actuate_and_observe + CircuitRetainedTime string // own | earlier + // Exempt holds leg:field pairs; a leg so named is exempt from freshness + // when that field is the only one the revision changed against a match. + Exempt map[string]bool + // ExemptSets holds a leg and a field set; the leg is exempt when the + // revision changed exactly those fields against a match. + ExemptSets []ExemptSet + // ExemptAtLeast maps a leg to a count; the leg is exempt when the revision + // changed at least that many fields against a match. + ExemptAtLeast map[string]int + // ExemptKindChange exempts the circuit leg on a change of actuator kind in + // the named direction: "firmware" (GPIO to firmware) or "GPIO" (firmware + // to GPIO). + ExemptKindChange map[string]bool + ExemptControlBehindPreEnergisation bool + // ExemptPostures holds leg:posture pairs; the leg is exempt in that posture. + ExemptPostures map[string]bool + ControlRetainedTime string // own | later +} + +// ExemptSet names a leg and the exact field set that exempts it. +type ExemptSet struct { + Leg string + Fields []string +} + +// ReferenceRule is the contract's reading. +var ReferenceRule = RevisionRule{ + MatchName: true, MatchActuator: true, MatchSensor: true, + SensorMatch: "sensor_id", GPIOMatch: "pin", FirmwareMatch: "identity", + ChangeIdentity: true, IdentityCompare: "whole", ChangeMapping: true, + ChangeSensor: "whole", Visit: "all", + CircuitUnclaimedExempt: true, ControlRequiresClaim: true, + ControlOn: "any_change", ControlMissing: "fresh", + ClaimedMethods: "any_but_undemonstrated", CircuitRetainedTime: "own", + ControlRetainedTime: "own", +} + +// VerifyWithRule runs every stage, with the revision rule read as rule. +func VerifyWithRule(raw []byte, ctx Context, rule RevisionRule) (*Accepted, error) { + return verifyEnvelope(raw, ctx, func(b *parsedBinding, prior map[string]ZoneState) *Refusal { + if r := stObservations(b); r != nil { + return r + } + return rule.check(b, prior, ctx.DeploymentPosture) + }) +} + +type heldZone struct { + zoneID string + was ZoneState + ways map[string]bool +} + +func (rule RevisionRule) check(b *parsedBinding, prior map[string]ZoneState, posture string) *Refusal { + ids := make([]string, 0, len(prior)) + for id := range prior { + ids = append(ids, id) + } + sort.Slice(ids, func(i, j int) bool { + a, c := prior[ids[i]], prior[ids[j]] + if a.Seq != c.Seq { + return a.Seq < c.Seq + } + return ids[i] < ids[j] + }) + consumed := map[string]bool{} + for _, z := range b.zones { + var held []heldZone + for _, id := range ids { + if rule.OneToOne && consumed[id] { + continue + } + if ways := rule.ways(id, prior[id], z); len(ways) > 0 { + held = append(held, heldZone{id, prior[id], ways}) + } + } + if rule.OneToOne { + for _, h := range held { + consumed[h.zoneID] = true + } + } + if rule.FreshAgainstEveryMatchOnceChanged { + anyChanged := false + for _, h := range held { + if len(rule.changes(h.zoneID, h.was, z)) > 0 { + anyChanged = true + } + } + if anyChanged { + for _, h := range held { + if rule.stale(z, h.was, map[string]bool{"identity": true}, len(held) == 1, posture) { + return refuse(StageProofConsistency, ReasonStaleProof) + } + } + continue + } + } + held = rule.visit(held) + for _, h := range held { + changed := rule.changes(h.zoneID, h.was, z) + if len(changed) == 0 { + if rule.Visit == "break_on_unchanged" { + break + } + continue + } + if rule.stale(z, h.was, changed, len(held) == 1, posture) { + return refuse(StageProofConsistency, ReasonStaleProof) + } + if rule.Visit == "stop_after_pass" { + break + } + } + } + return nil +} + +func (rule RevisionRule) visit(held []heldZone) []heldZone { + switch rule.Visit { + case "first": + if len(held) > 1 { + return held[:1] + } + case "last": + if len(held) > 1 { + return held[len(held)-1:] + } + case "latest_proof": + if len(held) > 0 { + best := held[0] + for _, h := range held[1:] { + if h.was.ProofAtMs > best.was.ProofAtMs { + best = h + } + } + return []heldZone{best} + } + case "sensor_first": + for _, h := range held { + if h.ways["sensor"] { + return []heldZone{h} + } + } + if len(held) > 1 { + return held[:1] + } + case "name_if_no_actuator": + anyActuator := false + for _, h := range held { + if h.ways["actuator"] { + anyActuator = true + } + } + if anyActuator { + var kept []heldZone + for _, h := range held { + if !(len(h.ways) == 1 && h.ways["name"]) { + kept = append(kept, h) + } + } + return kept + } + } + return held +} + +func (rule RevisionRule) ways(zoneID string, was ZoneState, z parsedZone) map[string]bool { + ways := map[string]bool{} + if rule.MatchName && zoneID == z.zoneID { + ways["name"] = true + } + if rule.MatchActuator && rule.sameActuator(was.Identity, z.identity) { + ways["actuator"] = true + } + if rule.MatchSensor && rule.sameSensor(was.Sensor, z.sensor) { + ways["sensor"] = true + } + return ways +} + +func (rule RevisionRule) sameActuator(retained, identity map[string]any) bool { + pinA, okA := retained["gpio_pin"] + pinB, okB := identity["gpio_pin"] + if okA && okB { + if rule.GPIOMatch == "whole" { + return sameIdentity(retained, identity) + } + return sameIdentity(map[string]any{"gpio_pin": pinA}, map[string]any{"gpio_pin": pinB}) + } + switch rule.FirmwareMatch { + case "board": + return sameIdentity(only(retained, "firmware_device_id"), only(identity, "firmware_device_id")) + case "channel": + return sameIdentity(only(retained, "channel"), only(identity, "channel")) + } + return sameIdentity(retained, identity) +} + +func (rule RevisionRule) sameSensor(was, now Sensor) bool { + switch rule.SensorMatch { + case "whole": + return was == now + } + if field, ok := strings.CutPrefix(rule.SensorMatch, "id_and:"); ok { + return was.SensorID == now.SensorID && sensorField(was, field) == sensorField(now, field) + } + return was.SensorID == now.SensorID +} + +func (rule RevisionRule) changes(zoneID string, was ZoneState, z parsedZone) map[string]bool { + changed := map[string]bool{} + if rule.ChangeIdentity { + a, c := was.Identity, z.identity + switch rule.IdentityCompare { + case "ignore_board": + a, c = without(a, "firmware_device_id"), without(c, "firmware_device_id") + case "ignore_channel": + a, c = without(a, "channel"), without(c, "channel") + } + if !sameIdentity(a, c) { + changed["identity"] = true + } + } + if rule.ChangeMapping && was.Mapping != z.mapping { + changed["mapping"] = true + } + var differs bool + switch rule.ChangeSensor { + case "ignore:calibration_ref", "ignore:range", "ignore:range_min", "ignore:unit", + "ignore:direction", "ignore:quantity": + differs = blank(was.Sensor, rule.ChangeSensor) != blank(z.sensor, rule.ChangeSensor) + case "sensor_id": + differs = was.Sensor.SensorID != z.sensor.SensorID + case "id_and_calibration": + differs = was.Sensor.SensorID != z.sensor.SensorID || + was.Sensor.CalibrationRef != z.sensor.CalibrationRef + default: + differs = was.Sensor != z.sensor + } + if differs { + changed["sensor"] = true + } + if rule.ProofChangeIsChange { + legDiffers := z.controlMethod != "" && + (was.ControlProofAtMs == nil || z.controlPerformedAtMs != *was.ControlProofAtMs) + if z.performedAtMs != was.ProofAtMs || legDiffers { + changed["proof"] = true + } + } + if rule.RenameIsChange && zoneID != z.zoneID { + changed["name"] = true + } + return changed +} + +func (rule RevisionRule) stale(z parsedZone, was ZoneState, changed map[string]bool, single bool, posture string) bool { + unclaimed := z.method == MethodUnproven + if rule.ClaimedMethods == "actuate_and_observe" { + unclaimed = z.method != MethodActuate + } + hasLeg := z.controlMethod != "" + controlFresh := z.controlMethod == ControlCommanded && was.ControlProofAtMs != nil && + z.controlPerformedAtMs > *was.ControlProofAtMs + checkCircuit := !(rule.CircuitUnclaimedExempt && unclaimed) + if rule.CircuitSkipIfControlUnclaimed && z.controlMethod == ControlUnproven { + checkCircuit = false + } + circuitRetained := was.ProofAtMs + if rule.exempt("circuit", z, was, posture) { + checkCircuit = false + } + if rule.CircuitRetainedTime == "earlier" && was.ControlProofAtMs != nil { + circuitRetained = min(was.ProofAtMs, *was.ControlProofAtMs) + } + if rule.SingleRetainedTime && was.ControlProofAtMs != nil { + circuitRetained = max(was.ProofAtMs, *was.ControlProofAtMs) + } + if rule.CircuitSkipIfControlFresh && controlFresh { + checkCircuit = false + } + if rule.CircuitOnlySingleMatch && !single { + checkCircuit = false + } + if checkCircuit { + if rule.CircuitStrict && z.performedAtMs < circuitRetained || + !rule.CircuitStrict && z.performedAtMs <= circuitRetained { + return true + } + } + if !hasLeg { + return rule.ControlAbsentStale && !unclaimed && was.ControlProofAtMs != nil + } + if rule.ControlOnlySingleMatch && !single { + return false + } + if rule.exempt("control", z, was, posture) { + return false + } + if rule.ControlRequiresClaim && z.controlMethod != ControlCommanded { + return false + } + if rule.ControlSkipIfCircuitUnclaimed && unclaimed { + return false + } + if rule.ControlOn == "identity" && !changed["identity"] { + return false + } + if rule.ControlOn == "identity_or_mapping" && !changed["identity"] && !changed["mapping"] { + return false + } + var retained int64 + switch { + case was.ControlProofAtMs != nil: + retained = *was.ControlProofAtMs + if rule.SingleRetainedTime || rule.ControlRetainedTime == "later" { + retained = max(was.ProofAtMs, retained) + } + case rule.ControlMissing == "stale": + return true + case rule.ControlMissing == "circuit_time": + retained = was.ProofAtMs + default: + return false + } + if rule.ControlStrict { + return z.controlPerformedAtMs < retained + } + return z.controlPerformedAtMs <= retained +} + +func only(m map[string]any, key string) map[string]any { + out := map[string]any{} + if v, ok := m[key]; ok { + out[key] = v + } + return out +} + +func without(m map[string]any, key string) map[string]any { + out := make(map[string]any, len(m)) + for k, v := range m { + if k != key { + out[k] = v + } + } + return out +} + +// blank clears the sensor fields an ignore: reading leaves out of the change test. +func blank(s Sensor, reading string) Sensor { + switch reading { + case "ignore:calibration_ref": + s.CalibrationRef = "" + case "ignore:range": + s.RangeMin, s.RangeMax = 0, 0 + case "ignore:range_min": + s.RangeMin = 0 + case "ignore:unit": + s.Unit = "" + case "ignore:direction": + s.Direction = "" + case "ignore:quantity": + s.Quantity = "" + } + return s +} + +func (rule RevisionRule) exempt(leg string, z parsedZone, was ZoneState, posture string) bool { + fields := fieldChanges(z, was) + if len(fields) == 1 { + for field := range fields { + if rule.Exempt[leg+":"+field] { + return true + } + } + } + for _, set := range rule.ExemptSets { + if set.Leg != leg || len(set.Fields) != len(fields) { + continue + } + exact := true + for _, field := range set.Fields { + if !fields[field] { + exact = false + } + } + if exact { + return true + } + } + if k, ok := rule.ExemptAtLeast[leg]; ok && len(fields) >= k { + return true + } + if rule.ExemptPostures[leg+":"+posture] { + return true + } + if leg == "circuit" { + _, wasGPIO := was.Identity["gpio_pin"] + _, nowGPIO := z.identity["gpio_pin"] + if wasGPIO && !nowGPIO && rule.ExemptKindChange["firmware"] { + return true + } + if nowGPIO && !wasGPIO && rule.ExemptKindChange["GPIO"] { + return true + } + } + return leg == "control" && rule.ExemptControlBehindPreEnergisation && z.method == MethodPreEnergy +} + +// fieldChanges names the individual fields a revision changed against one +// retained zone. +func fieldChanges(z parsedZone, was ZoneState) map[string]bool { + fields := map[string]bool{} + keys := map[string]bool{} + for k := range was.Identity { + keys[k] = true + } + for k := range z.identity { + keys[k] = true + } + for k := range keys { + a, inA := was.Identity[k] + b, inB := z.identity[k] + if inA != inB || !sameIdentity(map[string]any{k: a}, map[string]any{k: b}) { + fields[k] = true + } + } + if was.Mapping != z.mapping { + fields["mapping"] = true + } + a, b := was.Sensor, z.sensor + for name, differs := range map[string]bool{ + "sensor_id": a.SensorID != b.SensorID, "quantity": a.Quantity != b.Quantity, + "unit": a.Unit != b.Unit, "range_min": a.RangeMin != b.RangeMin, + "range_max": a.RangeMax != b.RangeMax, "direction": a.Direction != b.Direction, + "noise_floor": a.NoiseFloor != b.NoiseFloor, "calibration_ref": a.CalibrationRef != b.CalibrationRef, + } { + if differs { + fields[name] = true + } + } + return fields +} + +// sensorField is one sensor field by its contract name, for id_and: readings. +func sensorField(s Sensor, name string) any { + switch name { + case "quantity": + return s.Quantity + case "unit": + return s.Unit + case "range_min": + return s.RangeMin + case "range_max": + return s.RangeMax + case "direction": + return s.Direction + case "noise_floor": + return s.NoiseFloor + case "calibration_ref": + return s.CalibrationRef + } + panic("unknown sensor field " + name) +} diff --git a/internal/binding/revision.go b/internal/binding/revision.go new file mode 100644 index 0000000..87a045e --- /dev/null +++ b/internal/binding/revision.go @@ -0,0 +1,70 @@ +// Copyright 2026 Ori Nexus Systems LTD +// SPDX-License-Identifier: Apache-2.0 + +package binding + +import "crypto/ed25519" + +// RetainedState is the per-zone record the revision rule reads, taken from the +// accepted binding in force exactly as a consumer retains it. +func RetainedState(a *Accepted) map[string]ZoneState { + out := make(map[string]ZoneState, len(a.Zones)) + for i, z := range a.Zones { + out[z.ZoneID] = ZoneState{ + Seq: i, + Identity: z.Identity, + Mapping: z.Mapping, + Sensor: z.Sensor, + ProofAtMs: z.ProofPerformedAtMs, + ControlProofAtMs: z.ControlProofPerformedAtMs, + } + } + return out +} + +// CheckRevision runs, over an unsigned revision draft, every stage a consumer +// decides from the document, the zone state it retained, and its declared +// inventory and posture: everything except the signature and its authority. +// +// A draft carries none of the fields signing owns, and no stage run here reads +// them, so stand-ins are supplied only to make the bytes parse. The revision +// rule is the verifier's own, so what is refused here is what a runtime would +// refuse as stale_proof. +func (b Binding) CheckRevision(prior map[string]ZoneState, ctx Context) error { + standIn := b + standIn.IssuedAtMs = 1 + standIn.SignerID, standIn.Actor, standIn.Reason = "draft", "draft", "draft" + standIn.SigningKey = SigningKeyName(make(ed25519.PublicKey, ed25519.PublicKeySize)) + preimage, err := standIn.Preimage() + if err != nil { + return err + } + value, r := decodeWire(preimage) + if r != nil { + return r + } + body, ok := value.(map[string]any) + if !ok { + return malformed() + } + parsed, r := stParses(body) + if r != nil { + return r + } + for _, stage := range []func() *Refusal{ + func() *Refusal { return stMappingSelfConsistency(parsed) }, + func() *Refusal { return stProofConsistency(parsed, prior) }, + func() *Refusal { return stBounds(parsed, ctx.ProfileMultiplier) }, + func() *Refusal { return stDisambiguation(parsed) }, + func() *Refusal { return stInventory(parsed, ctx) }, + func() *Refusal { return stActivationPosture(parsed, ctx.DeploymentPosture) }, + } { + if r := stage(); r != nil { + return r + } + } + return nil +} + +// IsDigest reports whether s is a canonical hash as the contract spells one. +func IsDigest(s string) bool { return digestPattern.MatchString(s) } diff --git a/internal/binding/revision_rule_adequacy_test.go b/internal/binding/revision_rule_adequacy_test.go new file mode 100644 index 0000000..91baba1 --- /dev/null +++ b/internal/binding/revision_rule_adequacy_test.go @@ -0,0 +1,289 @@ +// Copyright 2026 Ori Nexus Systems LTD +// SPDX-License-Identifier: Apache-2.0 + +package binding_test + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "reflect" + "sort" + "strings" + "testing" + + "github.com/ori-platform/ori-cli/internal/binding" +) + +// The corpus must refuse every wrong reading of the revision rule, not only +// agree with this verifier: a consumer that read the rule one of these ways +// would otherwise pass every case. The readings are ori-specs' +// revision-misreadings-v1.json, vendored beside the corpus under the same pin, +// so the contract's checker, the runtime's harness and this test hold the +// corpus to one table. It guards those misreadings and no others. +const misreadingsFile = "revision-misreadings-v1.json" + +type misreadingTable struct { + Reference map[string]json.RawMessage `json:"reference"` + ChangeEvents map[string][]string `json:"change_events"` + Misreadings map[string]map[string]json.RawMessage `json:"misreadings"` + referenceRule binding.RevisionRule +} + +func loadMisreadingTable(t *testing.T) misreadingTable { + t.Helper() + raw, err := os.ReadFile(filepath.Join(corpusDir, misreadingsFile)) + if err != nil { + t.Fatalf("read misreading table: %v", err) + } + var table misreadingTable + if err := json.Unmarshal(raw, &table); err != nil { + t.Fatalf("decode misreading table: %v", err) + } + for name := range revisionSwitches(&binding.RevisionRule{}) { + if _, ok := table.Reference[name]; !ok { + t.Fatalf("the table's reference omits the switch %q", name) + } + } + if err := applySwitches(&table.referenceRule, table.Reference); err != nil { + t.Fatalf("the table's reference: %v", err) + } + return table +} + +// revisionSwitches maps each switch name in the table to a setter on rule. +func revisionSwitches(rule *binding.RevisionRule) map[string]func(json.RawMessage) error { + strict := func(raw json.RawMessage, into any) error { + dec := json.NewDecoder(strings.NewReader(string(raw))) + dec.DisallowUnknownFields() + return dec.Decode(into) + } + flag := func(field *bool) func(json.RawMessage) error { + return func(raw json.RawMessage) error { return strict(raw, field) } + } + text := func(field *string) func(json.RawMessage) error { + return func(raw json.RawMessage) error { return strict(raw, field) } + } + // A pair list decodes into leg:value keys; empty leaves the switch unset. + pairs := func(field *map[string]bool) func(json.RawMessage) error { + return func(raw json.RawMessage) error { + var list [][2]string + if err := strict(raw, &list); err != nil { + return err + } + *field = nil + for _, pair := range list { + if *field == nil { + *field = map[string]bool{} + } + (*field)[pair[0]+":"+pair[1]] = true + } + return nil + } + } + return map[string]func(json.RawMessage) error{ + "match_name": flag(&rule.MatchName), + "match_actuator": flag(&rule.MatchActuator), + "match_sensor": flag(&rule.MatchSensor), + "sensor_match": text(&rule.SensorMatch), + "gpio_match": text(&rule.GPIOMatch), + "firmware_match": text(&rule.FirmwareMatch), + "change_identity": flag(&rule.ChangeIdentity), + "identity_compare": text(&rule.IdentityCompare), + "change_mapping": flag(&rule.ChangeMapping), + "change_sensor": text(&rule.ChangeSensor), + "rename_is_change": flag(&rule.RenameIsChange), + "visit": text(&rule.Visit), + "circuit_unclaimed_exempt": flag(&rule.CircuitUnclaimedExempt), + "circuit_skip_if_control_fresh": flag(&rule.CircuitSkipIfControlFresh), + "circuit_only_single_match": flag(&rule.CircuitOnlySingleMatch), + "circuit_strict": flag(&rule.CircuitStrict), + "control_requires_claim": flag(&rule.ControlRequiresClaim), + "control_on": text(&rule.ControlOn), + "control_skip_if_circuit_unclaimed": flag(&rule.ControlSkipIfCircuitUnclaimed), + "control_missing": text(&rule.ControlMissing), + "control_strict": flag(&rule.ControlStrict), + "one_to_one": flag(&rule.OneToOne), + "control_only_single_match": flag(&rule.ControlOnlySingleMatch), + "circuit_skip_if_control_unclaimed": flag(&rule.CircuitSkipIfControlUnclaimed), + "control_absent_stale": flag(&rule.ControlAbsentStale), + "single_retained_time": flag(&rule.SingleRetainedTime), + "fresh_against_every_match_once_changed": flag(&rule.FreshAgainstEveryMatchOnceChanged), + "proof_change_is_change": flag(&rule.ProofChangeIsChange), + "claimed_methods": text(&rule.ClaimedMethods), + "circuit_retained_time": text(&rule.CircuitRetainedTime), + "control_retained_time": text(&rule.ControlRetainedTime), + "exempt_control_behind_pre_energisation": flag(&rule.ExemptControlBehindPreEnergisation), + "exempt": pairs(&rule.Exempt), + "exempt_postures": pairs(&rule.ExemptPostures), + "exempt_sets": func(raw json.RawMessage) error { + var list [][2]json.RawMessage + if err := strict(raw, &list); err != nil { + return err + } + rule.ExemptSets = nil + for _, entry := range list { + var set binding.ExemptSet + if err := strict(entry[0], &set.Leg); err != nil { + return err + } + if err := strict(entry[1], &set.Fields); err != nil { + return err + } + rule.ExemptSets = append(rule.ExemptSets, set) + } + return nil + }, + "exempt_at_least": func(raw json.RawMessage) error { + var list [][2]json.RawMessage + if err := strict(raw, &list); err != nil { + return err + } + rule.ExemptAtLeast = nil + for _, entry := range list { + var leg string + var k int + if err := strict(entry[0], &leg); err != nil { + return err + } + if err := strict(entry[1], &k); err != nil { + return err + } + if rule.ExemptAtLeast == nil { + rule.ExemptAtLeast = map[string]int{} + } + rule.ExemptAtLeast[leg] = k + } + return nil + }, + "exempt_kind_change": func(raw json.RawMessage) error { + var kinds []string + if err := strict(raw, &kinds); err != nil { + return err + } + rule.ExemptKindChange = nil + for _, kind := range kinds { + if rule.ExemptKindChange == nil { + rule.ExemptKindChange = map[string]bool{} + } + rule.ExemptKindChange[kind] = true + } + return nil + }, + } +} + +// applySwitches sets each named switch on rule, refusing a name it does not know. +func applySwitches(rule *binding.RevisionRule, switches map[string]json.RawMessage) error { + setters := revisionSwitches(rule) + names := make([]string, 0, len(switches)) + for name := range switches { + names = append(names, name) + } + sort.Strings(names) + for _, name := range names { + set, ok := setters[name] + if !ok { + return fmt.Errorf("unknown switch %q", name) + } + if err := set(switches[name]); err != nil { + return fmt.Errorf("switch %q: %w", name, err) + } + } + return nil +} + +// casesGotWrong lists the corpus cases a reading of the rule decides wrongly. +func casesGotWrong(t *testing.T, c fullCorpus, rule binding.RevisionRule) []string { + t.Helper() + var wrong []string + for _, vc := range c.Cases { + env := envelopeBytes("binding", vc.Binding, vc.SignatureB64) + if _, err := binding.VerifyWithRule(env, bindingContext(t, vc.VerifierContext), rule); err != nil { + wrong = append(wrong, vc.Name) + } + } + for _, rc := range c.RejectCases { + env := envelopeBytes("binding", rc.Binding, rc.SignatureB64) + _, err := binding.VerifyWithRule(env, bindingContext(t, rc.VerifierContext), rule) + var r *binding.Refusal + if !errors.As(err, &r) || r.Stage != rc.Stage || r.Reason != rc.Reason { + wrong = append(wrong, rc.Name) + } + } + return wrong +} + +// The table's reference reading must be the verifier's, or a surviving +// misreading proves nothing about the corpus. It must also be the reference +// the seeded comparison with the production rule uses. +func TestTheReferenceRuleAgreesWithTheWholeCorpus(t *testing.T) { + table := loadMisreadingTable(t) + if !reflect.DeepEqual(table.referenceRule, binding.ReferenceRule) { + t.Fatalf("the table's reference %+v is not ReferenceRule %+v", table.referenceRule, binding.ReferenceRule) + } + if wrong := casesGotWrong(t, loadFullCorpus(t), table.referenceRule); len(wrong) > 0 { + t.Fatalf("the reference reading gets %d cases wrong: %v", len(wrong), wrong) + } +} + +// Every override must name a switch this test can set, or a misreading would +// run as the reference and pass for the wrong reason. +func TestTheMisreadingTableIsNonEmptyAndKnown(t *testing.T) { + table := loadMisreadingTable(t) + if len(table.Misreadings) == 0 { + t.Fatal("the misreading table is empty: it would guard nothing") + } + for name, overrides := range table.Misreadings { + if len(overrides) == 0 { + t.Errorf("the misreading %q overrides no switch", name) + } + rule := table.referenceRule + if err := applySwitches(&rule, overrides); err != nil { + t.Errorf("the misreading %q: %v", name, err) + } + } +} + +func TestAnUnknownSwitchIsRefused(t *testing.T) { + rule := binding.ReferenceRule + err := applySwitches(&rule, map[string]json.RawMessage{"no_such_switch": json.RawMessage("true")}) + if err == nil { + t.Fatal("an unknown switch was accepted") + } +} + +func TestTheCorpusRefusesEveryMisreadingOfTheRule(t *testing.T) { + c := loadFullCorpus(t) + table := loadMisreadingTable(t) + if len(table.Misreadings) == 0 { + t.Fatal("the misreading table is empty: it would guard nothing") + } + events := make([]string, 0, len(table.ChangeEvents)) + for name := range table.ChangeEvents { + events = append(events, name) + } + sort.Strings(events) + names := make([]string, 0, len(table.Misreadings)) + for name := range table.Misreadings { + names = append(names, name) + } + sort.Strings(names) + for _, name := range names { + t.Run(name, func(t *testing.T) { + rule := table.referenceRule + if err := applySwitches(&rule, table.Misreadings[name]); err != nil { + t.Fatalf("the misreading %q: %v", name, err) + } + if len(casesGotWrong(t, c, rule)) == 0 { + t.Fatalf("no vector refuses the misreading %q: a consumer that read the "+ + "revision rule this way would pass every case. Add a vector it gets "+ + "wrong. This guard covers only the misreadings in %s; exemptions keyed "+ + "on a set of fields grow exponentially, so only the change_events sets "+ + "(%s) are enumerated.", name, misreadingsFile, strings.Join(events, ", ")) + } + }) + } +} diff --git a/internal/binding/revision_rule_reference_test.go b/internal/binding/revision_rule_reference_test.go new file mode 100644 index 0000000..269b8b1 --- /dev/null +++ b/internal/binding/revision_rule_reference_test.go @@ -0,0 +1,84 @@ +// Copyright 2026 Ori Nexus Systems LTD +// SPDX-License-Identifier: Apache-2.0 + +package binding + +import ( + "fmt" + "math/rand" + "testing" +) + +// TestTheReferenceIsTheProductionRuleBeyondTheCorpus compares the harness's +// reference reading with the production revision rule on seeded random +// revisions. Agreement on the corpus alone would let the reference drift from +// the verifier wherever the corpus is silent, and the misreadings would then be +// measured against the wrong rule. Only the revision rule is compared: the +// observation checks are not part of either side here. +func TestTheReferenceIsTheProductionRuleBeyondTheCorpus(t *testing.T) { + rng := rand.New(rand.NewSource(20260923)) + pins := []int{19, 21, 26} + sensors := []string{"s-a", "s-b", "s-c"} + pick := func(choices ...string) string { return choices[rng.Intn(len(choices))] } + at := func(choices ...int64) int64 { return choices[rng.Intn(len(choices))] } + // GPIO and firmware identities, every proof method, and several sensor + // fields, so the reference cannot drift from the verifier where the corpus + // is silent. + identity := func(index int) map[string]any { + if rng.Float64() < 0.25 { + return map[string]any{"firmware_device_id": pick("fw-1", "fw-2"), "channel": pick("r0", "r1")} + } + return map[string]any{"gpio_pin": pins[index], "active_high": rng.Intn(2) == 0} + } + sensor := func(id string) Sensor { + return Sensor{ + SensorID: id, + NoiseFloor: []float64{0.05, 0.07}[rng.Intn(2)], + RangeMin: []float64{0, 1}[rng.Intn(2)], + Unit: pick("ampere", "amp"), + CalibrationRef: pick("c1", "c2"), + } + } + mapping := func() Mapping { return Mapping{OpenProtectedCircuit: pick(CoilEnergised, CoilDeEnergised)} } + for i := 0; i < 20000; i++ { + prior := map[string]ZoneState{} + for index := 0; index < 1+rng.Intn(3); index++ { + state := ZoneState{ + Identity: identity(index), + Mapping: mapping(), + Sensor: sensor(sensors[index]), + ProofAtMs: at(0, 300, 600), + Seq: index, + } + if control := rng.Intn(4); control > 0 { + v := []int64{0, 300, 600}[control-1] + state.ControlProofAtMs = &v + } + prior[fmt.Sprintf("z%d", index)] = state + } + b := &parsedBinding{} + for index := 0; index < 1+rng.Intn(2); index++ { + z := parsedZone{ + zoneID: pick("z0", "z1", "z2", fmt.Sprintf("new%d", index)), + identity: identity(rng.Intn(3)), + mapping: mapping(), + sensor: sensor(sensors[rng.Intn(3)]), + method: pick(MethodActuate, MethodPreEnergy, MethodUnproven), + performedAtMs: at(0, 300, 600, 900), + } + if rng.Float64() < 0.7 { + z.controlMethod = pick(ControlCommanded, ControlUnproven) + z.controlPerformedAtMs = at(0, 300, 600, 900) + } + b.zones = append(b.zones, z) + } + // Posture varies so a reference that read it would diverge: the rule + // ignores posture. + posture := pick("production", "staging", "development") + production, reference := stRevisionRule(b, prior), ReferenceRule.check(b, prior, posture) + if (production == nil) != (reference == nil) { + t.Fatalf("case %d (%s): production %v, reference %v\nzones %+v\nretained %+v", + i, posture, production, reference, b.zones, prior) + } + } +} diff --git a/internal/binding/testdata/vectors/commissioned_safety_binding/MANIFEST.json b/internal/binding/testdata/vectors/commissioned_safety_binding/MANIFEST.json index 085079f..24186e8 100644 --- a/internal/binding/testdata/vectors/commissioned_safety_binding/MANIFEST.json +++ b/internal/binding/testdata/vectors/commissioned_safety_binding/MANIFEST.json @@ -1,9 +1,10 @@ { "source_repository": "ori-platform/ori-specs", "source_path": "commissioned-safety-binding", - "source_commit": "8f7ef9d6ff8a356075d26425d85fd85a301c9161", + "source_commit": "7d9a6e8b6eaf24fbde7e8c29b2ed0b637cfa4b6f", "note": "Vendored copy of the normative corpus. The producer must construct these documents from typed values and emit these exact bytes, and the verifier must reach every declared verdict, so it is a conformance fixture rather than a sample. Digests detect a local edit; the source commit is the provenance trail.", "files": { - "binding-vectors-v1.json": "89260e00e6476fbe9798ac6596c87011cf49194aadc1285c467e3ff5bfd72afc" + "binding-vectors-v1.json": "3856c229ea6ae2f1046a992582b659699c25843574c5e3f5952119ced3644c3d", + "revision-misreadings-v1.json": "178836e1d2162baf525d9fccf7a1c4aabd86c72a5a283deea9119e2b7e2fd35d" } } diff --git a/internal/binding/testdata/vectors/commissioned_safety_binding/binding-vectors-v1.json b/internal/binding/testdata/vectors/commissioned_safety_binding/binding-vectors-v1.json index f0cc659..ae159c6 100644 --- a/internal/binding/testdata/vectors/commissioned_safety_binding/binding-vectors-v1.json +++ b/internal/binding/testdata/vectors/commissioned_safety_binding/binding-vectors-v1.json @@ -1227,7 +1227,16 @@ "close_protected_circuit": "energised", "de_energised_terminal_state": "open" }, - "calibration_ref": "sct013-100-2026-08-19-a", + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, "proof_at_ms": 1800000000000 }, "borehole-pump": { @@ -1240,7 +1249,16 @@ "close_protected_circuit": "de_energised", "de_energised_terminal_state": "closed" }, - "calibration_ref": "sct013-100-2026-08-19-b", + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, "proof_at_ms": 1800000000000 } } @@ -1384,7 +1402,16 @@ "close_protected_circuit": "energised", "de_energised_terminal_state": "open" }, - "calibration_ref": "sct013-100-2026-08-19-a", + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, "proof_at_ms": 1800000000000, "control_proof_at_ms": 1800000600000 } @@ -1394,29 +1421,27 @@ "canonical_sha256": "sha256:1c2abef277451e5eb59ea4636f44bd0fc5f7d3a236fee99698ba130fe5e47b9e", "signature_b64": "EaR7iqRBKSmMS1Y6F4Jj0GJkU+O+djoNFjQGIX2nnHUq2bAELW+zomJlrA8IMX0IsgNH5f1+OZmeZSsUIoq+BQ==", "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2264726976657220626f617264207265706c616365643b2074686520737461676520696e7665727473222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a45615237697152424b536d4d5331593646344a6a30474a6b552b4f2b646a6f4e466a51474958326e6e485571326241454c572b7a6f6d4a6c724138494d58304973674e483566312b4f5a6d655a537355496f712b42513d3d227d" - } - ], - "reject_cases": [ + }, { - "name": "transposed_binding", - "note": "The contact was observed to open and the instrument still finds the load energised afterwards, because the clamp is on a different circuit from the contactor. This is the transposition case, and it is caught by the instrument's own load determination rather than by reading a threshold into a current value.", + "name": "capacity_only_revision_keeps_its_proof", + "note": "The revision changes `rated_capacity` and carries both proof legs, each exactly as old as the retained record. Capacity is the one zone field a proof does not establish, so the revision reaches in force after its bounds are checked again. The retained state holds no capacity, so a consumer cannot tell this case from an unchanged revision; what it pins is that a carried proof on a zone whose sensor, actuator and mapping are unchanged is accepted.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "breaker upgraded from 10 A to 16 A", "zones": [ { "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 10.0, + "value": 16.0, "provenance": "nameplate" }, "sensor": { @@ -1450,9 +1475,9 @@ "coil_state": "de_energised", "gpio_level": "high", "load_present_before": true, - "load_present_after": true, + "load_present_after": false, "sensor_before": 6.4, - "sensor_after": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { @@ -1465,31 +1490,129 @@ "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } - }, + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22627265616b65722075706772616465642066726f6d203130204120746f2031362041222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31362e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:10c8d047a4a3e6e7e98bf14532150c7fb5267430911a14fe7bd4f3fac016458c", + "signature_b64": "L0iUeao5hvq34wmTmkoL6Fk7P1/zorkZl/emM06AsYPHoI4vMov0MkfN8o0BswHlvrukt+Wuwe7lxwyNIQo/Aw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22627265616b65722075706772616465642066726f6d203130204120746f2031362041222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31362e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a4c30695565616f356876713334776d546d6b6f4c36466b3750312f7a6f726b5a6c2f656d4d303641735950486f4934764d6f76304d6b664e386f30427377486c7672756b742b57757765376c7877794e49516f2f41773d3d227d" + }, + { + "name": "revision_after_a_record_with_no_control_leg", + "note": "The retained record carried no control leg, so there is no control time for a revision's control leg to follow. The revision rewires the mapping and carries a fresh circuit leg and a control leg; with nothing retained to inherit, the control leg is fresh by construction and the zone reaches in force.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired and both legs proven", + "zones": [ { - "zone_id": "borehole-pump", + "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 4.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-main", "quantity": "current", "unit": "ampere", "range_min": 0.0, "range_max": 100.0, "direction": "positive_is_load_draw", "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" + "calibration_ref": "sct013-100-2026-08-19-a" }, "actuator": { - "kind": "firmware_channel", + "kind": "local_gpio", "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "gpio_pin": 26, + "active_high": false }, "commissioned_mapping": { "open_protected_circuit": "energised", @@ -1499,43 +1622,70 @@ }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", "coil_state": "energised", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -1544,44 +1694,58 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:0bdf6c15f85e5ac9f325d9fdf78d506d5ad06ec0b098b6661d8cad1d8491bd9c", - "signature_b64": "mwMxOUWsv0yvnCty7ouqfvXvzEDRjPPZOTrTFBt/B2jYdP0Zce++k8Plmem2mB49A05MelGMtAd67EBBAJfdDg==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a6d774d784f555773763079766e437479376f7571667658767a4544526a50505a4f5472544642742f42326a596450305a63652b2b6b38506c6d656d326d4234394130354d656c474d7441643637454242414a666444673d3d227d", - "reason": "proof_contradiction", - "stage": "proof_consistency", - "signature_valid": true + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:6d8d0edad7501b7e8dffad01572239ed43bc2d92d0334ba15b99a646e464f08d", + "signature_b64": "NUANLxhoqPfrluVJEm1T/0Oiq+Pj+19df+UQcSMoSSkGege71xH4Aeq2QBKJDlwLcB9RldeLu8Lpi6T7tCA1Dg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a4e55414e4c78686f715066726c75564a456d31542f304f69712b506a2b313964662b555163534d6f53536b4765676537317848344165713251424b4a446c774c634239526c64654c75384c70693654377443413144673d3d227d" }, { - "name": "terminal_state_observed_contradicts_command", - "note": "The contact was observed closed after a command to open the circuit.", + "name": "zone_renamed_on_the_same_hardware_keeps_its_proof", + "note": "The revision renames the zone and changes nothing else. A zone's name labels it; the proof established the sensor, the actuator and the mapping, and none of those moved, so the carried legs stand and the zone reaches in force.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "zone renamed", "zones": [ { - "zone_id": "main-distribution", + "zone_id": "main-circuit", "rated_capacity": { "parameter": "rated_capacity_amps", "value": 10.0, @@ -1621,7 +1785,7 @@ "load_present_after": false, "sensor_before": 6.4, "sensor_after": 0.02, - "terminal_state_observed": "closed" + "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", @@ -1633,77 +1797,48 @@ "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, - "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "energised", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "de_energised", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, - "terminal_state_observed": "closed" - } - ] } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -1712,41 +1847,56 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:6a3a544ce101df7cb785863b22b58b92e85c8f866f762de3ad614a3504bfdb3e", - "signature_b64": "PMrP69s/9+kBotiCIXJiBKsY+oeQHowJQqR0508PSnzxvCbQfqktwqIHajdejJJbcnL5GWaSgzPhtfdF01/nDw==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a504d72503639732f392b6b426f74694349584a69424b73592b6f6551486f774a5171523035303850536e7a787643625166716b7477714948616a64656a4a4a62636e4c3547576153677a50687466644630312f6e44773d3d227d", - "reason": "proof_contradiction", - "stage": "proof_consistency", - "signature_valid": true + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d6564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d63697263756974227d5d7d", + "canonical_sha256": "sha256:099b3d263ef810dd21a80fd4155a3133b9d5577aef7b3c71d38827ef698fa82f", + "signature_b64": "lOApglHThl6BS/Vfn+kxd0bLoF5IfKdNFGOlUpDvFQmA5oK5Wnq1WEszTzjUcLPdwQU+ZFf3Ps5ZwMt+b+NAAg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d6564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d63697263756974227d5d7d2c227369676e6174757265223a22656432353531393a6c4f4170676c4854686c3642532f56666e2b6b786430624c6f463549664b644e46474f6c5570447646516d41356f4b35576e71315745737a547a6a55634c50647751552b5a4666335073355a774d742b622b4e4141673d3d227d" }, { - "name": "proof_performed_on_an_idle_load", - "note": "The load was not drawing before the open command, so opening it demonstrated nothing: an idle circuit reads the same on both sides of an actuation. A low reading after the command is not on its own evidence that this contactor controls this circuit.", + "name": "another_channel_on_the_same_board_is_not_its_predecessor", + "note": "The same board on another channel is a different actuator. Nothing retained shares its name, its sensor or its identity, so there is no proof for it to inherit; it is verified as a new zone, provisional as every firmware zone is. A consumer that matched firmware actuators on the board alone would refuse it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "pump moved to the board's second relay; clamp moved to the tank", "zones": [ { "zone_id": "main-distribution", @@ -1785,9 +1935,9 @@ "commanded": "open_protected_circuit", "coil_state": "de_energised", "gpio_level": "high", - "load_present_before": false, + "load_present_before": true, "load_present_after": false, - "sensor_before": 0.02, + "sensor_before": 6.4, "sensor_after": 0.02, "terminal_state_observed": "open" }, @@ -1805,14 +1955,14 @@ } }, { - "zone_id": "borehole-pump", + "zone_id": "tank-circuit", "rated_capacity": { "parameter": "rated_capacity_amps", "value": 4.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-tank", "quantity": "current", "unit": "ampere", "range_min": 0.0, @@ -1825,7 +1975,7 @@ "kind": "firmware_channel", "identity": { "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "channel": "relay1" }, "commissioned_mapping": { "open_protected_circuit": "energised", @@ -1866,12 +2016,12 @@ "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", "declared_inventory": { "sensor_ids": [ "load-current-main", - "load-current-pump" + "load-current-tank" ], "actuators": [ { @@ -1885,36 +2035,79 @@ "kind": "firmware_channel", "identity": { "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "channel": "relay1" } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000 + }, + "borehole-pump": { + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "proof_at_ms": 1800000000000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:da20e680955f44ee23d6e8c8825c11ae7f596a4fe5e51d329b15d0a77f4c13b5", - "signature_b64": "aa+kwsIfpK2+OFn6wJXx7MhyQytzJIT4/S2T1JLAKfJIe6eP7IrrZqi2tQI7N0jNc42/QqqHvrGX9wQ+tx30Cg==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a61612b6b77734966704b322b4f466e36774a5878374d68795179747a4a4954342f533254314a4c414b664a4965366550374972725a716932745149374e306a4e6334322f51717148767247583977512b7478333043673d3d227d", - "reason": "proof_contradiction", - "stage": "proof_consistency", - "signature_valid": true + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70206d6f76656420746f2074686520626f6172642773207365636f6e642072656c61793b20636c616d70206d6f76656420746f207468652074616e6b222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617931222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d74616e6b222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a2274616e6b2d63697263756974227d5d7d", + "canonical_sha256": "sha256:78cb7db0d6b42d939ec048ea22c1e4c61daf8e3d1f2ab0272d310026c963366b", + "signature_b64": "M7NzIt2Z869+ErYvLvb3LC6oZSxYwaB1rr5P8PsHxf56a2lUwNlby7oGF2VIy+SPv9El154MWnY/+UgsnIrfDQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70206d6f76656420746f2074686520626f6172642773207365636f6e642072656c61793b20636c616d70206d6f76656420746f207468652074616e6b222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617931222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d74616e6b222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a2274616e6b2d63697263756974227d5d7d2c227369676e6174757265223a22656432353531393a4d374e7a4974325a3836392b457259764c7662334c43366f5a5378597761423172723550385073487866353661326c55774e6c6279376f4746325649792b53507639456c3135344d576e592f2b5567736e49726644513d3d227d" }, { - "name": "proof_delta_within_the_sensor_noise_floor", - "note": "The instrument reports the load gone, and the recorded current moved by 0.02 A against a declared noise floor of 0.05 A. A change the sensor cannot resolve is not a measurement, whatever the instrument says.", + "name": "an_unclaimed_leg_is_not_held_to_the_retained_proof", + "note": "The mapping is rewired and the circuit leg is recorded undemonstrated, with the time of the retained proof. A leg the revision does not claim carries no proof, so it is not held to the retained time: the zone is provisional, never in force, and never refused as stale.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "contactor rewired; not yet proven", "zones": [ { "zone_id": "main-distribution", @@ -1940,90 +2133,16 @@ "active_high": false }, "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" } }, "proof": { - "method": "actuate_and_observe", + "method": "undemonstrated", "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "de_energised", - "gpio_level": "high", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 6.4, - "sensor_after": 6.38, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "low", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.02, - "sensor_after": 6.4, - "terminal_state_observed": "closed" - } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, - "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" - } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "energised", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "de_energised", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, - "terminal_state_observed": "closed" - } - ] + "reason": "rewired; proof to follow", + "observations": [] } } ] @@ -2034,12 +2153,11 @@ "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -2048,41 +2166,56 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, - "deployment_posture": "production", - "profile_multiplier": 5.0 + "deployment_posture": "development", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e33382c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:1257364080aa5184414ea4c575b366acb0bdd1b7ae34fa0af1d9a95f12b6f22e", - "signature_b64": "U26eyrEzVadKBmZ0X18+Fe+XVTOtIs7EVHqxuArXPYo2i4tGVO4TNGDPQuEWCH33ixUA4Tx0EdnUf9O2QOKdBA==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e33382c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a553236657972457a5661644b426d5a305831382b46652b5856544f7449733745564871787541725850596f3269347447564f34544e4744505175455743483333697855413454783045646e5566394f32514f4b6442413d3d227d", - "reason": "proof_contradiction", - "stage": "proof_consistency", - "signature_valid": true + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b206e6f74207965742070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22726577697265643b2070726f6f6620746f20666f6c6c6f77227d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:a8e9997c5a8a17de92ae0ad5d9c683490f2153b8e32ce7bf59fb157eed918fe0", + "signature_b64": "DoUEnzoLVLR/2BVpULdIGwZjnb/NWuz0dVitKqgJwNb6Qt4XLNaTaeQvuRcXynaJS2+xyQd1y91hwpztB3X5AA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b206e6f74207965742070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22726577697265643b2070726f6f6620746f20666f6c6c6f77227d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a446f55456e7a6f4c564c522f32425670554c644947775a6a6e622f4e57757a30645669744b71674a774e6236517434584c4e61546165517675526358796e614a53322b78795164317939316877707a744233583541413d3d227d" }, { - "name": "proof_open_observed_without_the_load_it_interrupted", - "note": "The recorded current falls well past the noise floor, and the instrument reports no load present on either side of the open command. Only the instrument's classification contradicts the command here, so a verifier that reads the sensor values and skips the booleans accepts it. The readings are evidence; the instrument decides.", + "name": "an_unclaimed_control_leg_is_not_held_to_the_retained_proof", + "note": "The mapping is rewired and the circuit leg redone; the control leg is recorded undemonstrated with the time of the retained proof. A leg the revision does not claim is held to no time, so the zone is provisional and not refused as stale.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "contactor rewired; circuit re-proven, control leg to follow", "zones": [ { "zone_id": "main-distribution", @@ -2107,62 +2240,6 @@ "gpio_pin": 26, "active_high": false }, - "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" - } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "de_energised", - "gpio_level": "high", - "load_present_before": false, - "load_present_after": false, - "sensor_before": 6.4, - "sensor_after": 0.02, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "low", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.02, - "sensor_after": 6.4, - "terminal_state_observed": "closed" - } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, "commissioned_mapping": { "open_protected_circuit": "energised", "close_protected_circuit": "de_energised", @@ -2171,27 +2248,35 @@ }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", "coil_state": "energised", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "undemonstrated", + "performed_at_ms": 1800000000000, + "reason": "control leg to follow", + "observations": [] + } } } ] @@ -2202,12 +2287,11 @@ "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -2216,41 +2300,56 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, - "deployment_posture": "production", - "profile_multiplier": 5.0 + "deployment_posture": "development", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:9a2edf4a30b8ca6d3e0a227566e673acb1d61b4ba3d922141eb25f3b07210092", - "signature_b64": "lY7dYaecaKKWppo/bSLZNcsNMd7aeBLbtJVI6mprcy0kKGUxVKjAsie/CIiMh7t6yxuhBzMjeI8KUWM6/95nAQ==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a6c59376459616563614b4b5770706f2f62534c5a4e63734e4d64376165424c62744a5649366d70726379306b4b475578564b6a417369652f4349694d6837743679787568427a4d6a6549384b55574d362f39356e41513d3d227d", - "reason": "proof_contradiction", - "stage": "proof_consistency", - "signature_valid": true + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636972637569742072652d70726f76656e2c20636f6e74726f6c206c656720746f20666f6c6c6f77222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e74726f6c206c656720746f20666f6c6c6f77227d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:fdd7d4cf423e3e55b05a6ae72bd5b2b9b2c35e0bd6813df0d6d56ce6cf7a729f", + "signature_b64": "jA7b7qGwqvG/UZPzKWB+8KuXbp8VKIMMkjQrW3no806a/Wy9s4QQ/gVakv+tORKkr/eUXg+0/TCDdm6e20BsBw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636972637569742072652d70726f76656e2c20636f6e74726f6c206c656720746f20666f6c6c6f77222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e74726f6c206c656720746f20666f6c6c6f77227d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6a413762377147777176472f555a507a4b57422b384b7558627038564b494d4d6b6a517257336e6f383036612f577939733451512f6756616b762b744f524b6b722f655558672b302f544344646d36653230427342773d3d227d" }, { - "name": "proof_close_observed_with_no_readings_and_the_load_already_present", - "note": "A close command on a circuit the instrument already reports energised establishes nothing, and this observation carries no readings at all, so the noise-floor rule cannot reach it. Without the classifier there is no rule left to refuse it.", + "name": "control_leg_dropped_on_a_changed_zone_is_provisional", + "note": "The mapping is rewired, the circuit leg redone and the control leg left out. The retained record has a control time, but an absent leg carries no proof and is held to none, so the zone is provisional and not refused as stale.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "contactor rewired; circuit re-proven, control leg dropped", "zones": [ { "zone_id": "main-distribution", @@ -2276,19 +2375,19 @@ "active_high": false }, "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "de_energised", - "gpio_level": "high", + "coil_state": "energised", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, "sensor_before": 6.4, @@ -2297,64 +2396,12 @@ }, { "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "low", - "load_present_before": true, + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, "load_present_after": true, - "terminal_state_observed": "closed" - } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, - "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" - } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "energised", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "de_energised", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } ] @@ -2368,12 +2415,11 @@ "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -2382,41 +2428,56 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:4bd9d9ebf4ac25d9ce4a462b6ad059ec9c98b4b4e2a2d3791ef1c4e587eeeb71", - "signature_b64": "OqdbATZq7GNNAwdkvFTvGENbbFq2XhweafljXKT42IG5SSXr7n6OeSdfDAYXrEDxBdjXyvljzqElJ8KtG6wPCg==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a4f71646241545a7137474e4e4177646b7646547647454e62624671325868776561666c6a584b54343249473553535872376e364f65536466444159587245447842646a5879766c6a7a71456c4a384b744736775043673d3d227d", - "reason": "proof_contradiction", - "stage": "proof_consistency", - "signature_valid": true + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636972637569742072652d70726f76656e2c20636f6e74726f6c206c65672064726f70706564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:e6f012300497e9a23deb9d586c7c33b7fd796035fc60b44b47d69812fa8b900f", + "signature_b64": "teaTcyZTARll8dfNlgY26iPdx2/Vx0+NFgMHrtseVx0M7zoCaJmMvvujEtQDOG647Uh7KVqscbrj7Gv7p020BA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636972637569742072652d70726f76656e2c20636f6e74726f6c206c65672064726f70706564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a7465615463795a5441526c6c3864664e6c6759323669506478322f5678302b4e46674d48727473655678304d377a6f43614a6d4d7676756a457451444f473634375568374b5671736362726a374776377030323042413d3d227d" }, { - "name": "polarity_mismatch", - "note": "`active_high` is false, so a de-energised coil is driven by a high GPIO level. The observation records a low level for the de-energised command, which contradicts the declared driver polarity.", + "name": "circuit_leg_between_the_two_retained_times_is_fresh", + "note": "The circuit leg follows the retained circuit proof and precedes the retained control proof; the control leg follows the retained control proof. Each leg is held to the retained time of the same leg, so both are fresh; a consumer that held both to the later of the two retained times refuses it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "contactor rewired and both legs proven", "zones": [ { "zone_id": "main-distribution", @@ -2442,18 +2503,18 @@ "active_high": false }, "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000300000, "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "de_energised", + "coil_state": "energised", "gpio_level": "low", "load_present_before": true, "load_present_after": false, @@ -2463,85 +2524,56 @@ }, { "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "low", + "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, "sensor_before": 0.02, "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, - "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "energised", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "de_energised", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, - "terminal_state_observed": "closed" - } - ] } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -2550,44 +2582,59 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:04d60c08b68d923c5350266810a706bce1cd1104fccbe0f55a7c7079c27890fd", - "signature_b64": "JyKb1vOhEo9gZ3F0iUtQ+Afe3U7zers62gNy/U8mBig0u2H4hCHEy+iVgWmAkM0bdh+Cq5RuVbtNEQ23NSM1DA==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a4a794b6231764f68456f39675a334630695574512b4166653355377a6572733632674e792f55386d426967307532483468434845792b695667576d416b4d306264682b43713552755662744e455132334e534d3144413d3d227d", - "reason": "proof_contradiction", - "stage": "proof_consistency", - "signature_valid": true + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:0b7035c3534366003d026d737b9766e4f6770c62c365455bbbe1c5f48c9203b4", + "signature_b64": "9CIGgJAVu4ksZz9YA/Yw811LeFMJueOxyIogwrIhID/qnUSLBrYd4pss2Ef40OeZuAsoTqDW4zVJtHc5vPKwAA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a39434947674a415675346b735a7a3959412f59773831314c65464d4a75654f7879496f677772496849442f716e55534c427259643470737332456634304f655a7541736f54714457347a564a7448633576504b7741413d3d227d" }, { - "name": "outcomes_name_one_coil_state", - "note": "Both circuit outcomes map to `de_energised`. A coil has two states, so one of the two observations is wrong.", + "name": "name_taken_by_unchanged_hardware_fresh_against_that_zone", + "note": "The main circuit's hardware, unchanged, takes the name of the retained `feeder` zone with legs fresh against `feeder`. Against its own retained zone nothing changed, so it is not held to that zone's later proof; a consumer that, once any match changed, held the zone to every match refuses it. Its legs predate its own zone's retained proof, so this case depends on whether an unchanged zone may carry an older proof, which the contract leaves open.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "main circuit renamed to feeder and re-proven", "zones": [ { - "zone_id": "main-distribution", + "zone_id": "feeder", "rated_capacity": { "parameter": "rated_capacity_amps", "value": 10.0, @@ -2611,13 +2658,13 @@ }, "commissioned_mapping": { "open_protected_circuit": "de_energised", - "close_protected_circuit": "de_energised", + "close_protected_circuit": "energised", "de_energised_terminal_state": "open" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000600000, "observations": [ { "commanded": "open_protected_circuit", @@ -2639,77 +2686,10919 @@ "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000900000, + "control_proof_at_ms": 1800000900000 }, + "feeder": { + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e20636972637569742072656e616d656420746f2066656564657220616e642072652d70726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22666565646572227d5d7d", + "canonical_sha256": "sha256:fcfdc86ede0a6b592f16e2711007c25d1cde32c3750a16f384c9e7d04d578928", + "signature_b64": "S8jT7TAC6V5yJVj5c/DhVx8356chotWEvGYlSXI3KBoI5bYz0hwDoY8Iip9QiyVAbfp2mZjrN5ItGHL2p8haBw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e20636972637569742072656e616d656420746f2066656564657220616e642072652d70726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22666565646572227d5d7d2c227369676e6174757265223a22656432353531393a53386a5437544143365635794a566a35632f446856783833353663686f7457457647596c535849334b426f493562597a306877446f5938496970395169795641626670326d5a6a724e35497447484c327038686142773d3d227d" + }, + { + "name": "proof_only_revision_carries_its_control_leg", + "note": "Nothing in the zone changes; the circuit leg is re-proven and the control leg carried. A new proof time is not a change to the zone, so the carried control leg stands and the zone reaches in force.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "circuit leg re-proven; nothing changed", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2263697263756974206c65672072652d70726f76656e3b206e6f7468696e67206368616e676564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:13ccf5ab2c2a68d9e04628a9abc4675142923ad4eea1f4c79d1fe13a0f9d58a8", + "signature_b64": "Hwqv7XCAr25bb7OFZLNVGi2Swagh5E1QMH0GbloGVtgLPVDNkerNTIVozU7bIU/Whb4SFmd10mhj6aFweUosBQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2263697263756974206c65672072652d70726f76656e3b206e6f7468696e67206368616e676564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a48777176375843417232356262374f465a4c4e564769325377616768354531514d483047626c6f475674674c5056444e6b65724e5449566f7a55376249552f5768623453466d6431306d686a3661467765556f7342513d3d227d" + }, + { + "name": "control_leg_between_the_two_retained_times_is_fresh", + "note": "The retained control proof predates the retained circuit proof, and the new control leg falls between them. Each leg is held to the retained time of the same leg, so the control leg is fresh and the revision reaches in force; a consumer that held it to the later of the two retained times refuses it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired and both legs proven", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000300000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000600000, + "control_proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:f453879260cfa27ec85b9ed3c0c04c1c723c16f272a026138244e9b6d60ec3dc", + "signature_b64": "fKgl6oMX9eGtVtPFRKO1CZKtvZhnJJ6JotT9eesvYdwU3F4s2CVPU8bd65GUFOGl7G/pG8+JlLnT9R7uPdCjBw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a664b676c366f4d583965477456745046524b4f31435a4b74765a686e4a4a364a6f745439656573765964775533463473324356505538626436354755464f476c37472f7047382b4a6c4c6e54395237755064436a42773d3d227d" + }, + { + "name": "firmware_zone_on_another_board_is_not_its_predecessor", + "note": "The same channel name on a different board is a different actuator. Nothing retained shares its name, its sensor or its identity, so there is no proof for it to inherit and no revision rule to apply; it is verified as a new zone, provisional as every firmware zone is. A consumer that matched on the channel alone would refuse it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "actor": "installer:ade", + "reason": "pump zone renamed; clamp moved to the tank input", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "tank-circuit", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-tank", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-0d4e1a77", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-tank" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-0d4e1a77", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000 + }, + "borehole-pump": { + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70207a6f6e652072656e616d65643b20636c616d70206d6f76656420746f207468652074616e6b20696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3064346531613737227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d74616e6b222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a2274616e6b2d63697263756974227d5d7d", + "canonical_sha256": "sha256:b3dfdc0cd0761c09178c931f7cfec80bbf8a11e836ae0fc14046c6ebbef03bdb", + "signature_b64": "vd6wwkq7pu+oHyuGdqFBgt/u4a9x3rD08Nj20G4Yw3C6B4moJ6XhfNcikkDrDtJLbX5ea3PbAguc8qXveAY0DQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70207a6f6e652072656e616d65643b20636c616d70206d6f76656420746f207468652074616e6b20696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3064346531613737227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d74616e6b222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a2274616e6b2d63697263756974227d5d7d2c227369676e6174757265223a22656432353531393a76643677776b713770752b6f487975476471464267742f753461397833724430384e6a32304734597733433642346d6f4a365868664e63696b6b447244744a4c625835656133506241677563387158766541593044513d3d227d" + } + ], + "reject_cases": [ + { + "name": "transposed_binding", + "note": "The contact was observed to open and the instrument still finds the load energised afterwards, because the clamp is on a different circuit from the contactor. This is the transposition case, and it is caught by the instrument's own load determination rather than by reading a threshold into a current value.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": true, + "sensor_before": 6.4, + "sensor_after": 6.4, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:0bdf6c15f85e5ac9f325d9fdf78d506d5ad06ec0b098b6661d8cad1d8491bd9c", + "signature_b64": "mwMxOUWsv0yvnCty7ouqfvXvzEDRjPPZOTrTFBt/B2jYdP0Zce++k8Plmem2mB49A05MelGMtAd67EBBAJfdDg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a6d774d784f555773763079766e437479376f7571667658767a4544526a50505a4f5472544642742f42326a596450305a63652b2b6b38506c6d656d326d4234394130354d656c474d7441643637454242414a666444673d3d227d", + "reason": "proof_contradiction", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "terminal_state_observed_contradicts_command", + "note": "The contact was observed closed after a command to open the circuit.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "closed" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:6a3a544ce101df7cb785863b22b58b92e85c8f866f762de3ad614a3504bfdb3e", + "signature_b64": "PMrP69s/9+kBotiCIXJiBKsY+oeQHowJQqR0508PSnzxvCbQfqktwqIHajdejJJbcnL5GWaSgzPhtfdF01/nDw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a504d72503639732f392b6b426f74694349584a69424b73592b6f6551486f774a5171523035303850536e7a787643625166716b7477714948616a64656a4a4a62636e4c3547576153677a50687466644630312f6e44773d3d227d", + "reason": "proof_contradiction", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "proof_performed_on_an_idle_load", + "note": "The load was not drawing before the open command, so opening it demonstrated nothing: an idle circuit reads the same on both sides of an actuation. A low reading after the command is not on its own evidence that this contactor controls this circuit.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": false, + "sensor_before": 0.02, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:da20e680955f44ee23d6e8c8825c11ae7f596a4fe5e51d329b15d0a77f4c13b5", + "signature_b64": "aa+kwsIfpK2+OFn6wJXx7MhyQytzJIT4/S2T1JLAKfJIe6eP7IrrZqi2tQI7N0jNc42/QqqHvrGX9wQ+tx30Cg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a61612b6b77734966704b322b4f466e36774a5878374d68795179747a4a4954342f533254314a4c414b664a4965366550374972725a716932745149374e306a4e6334322f51717148767247583977512b7478333043673d3d227d", + "reason": "proof_contradiction", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "proof_delta_within_the_sensor_noise_floor", + "note": "The instrument reports the load gone, and the recorded current moved by 0.02 A against a declared noise floor of 0.05 A. A change the sensor cannot resolve is not a measurement, whatever the instrument says.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 6.38, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e33382c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:1257364080aa5184414ea4c575b366acb0bdd1b7ae34fa0af1d9a95f12b6f22e", + "signature_b64": "U26eyrEzVadKBmZ0X18+Fe+XVTOtIs7EVHqxuArXPYo2i4tGVO4TNGDPQuEWCH33ixUA4Tx0EdnUf9O2QOKdBA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a362e33382c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a553236657972457a5661644b426d5a305831382b46652b5856544f7449733745564871787541725850596f3269347447564f34544e4744505175455743483333697855413454783045646e5566394f32514f4b6442413d3d227d", + "reason": "proof_contradiction", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "proof_open_observed_without_the_load_it_interrupted", + "note": "The recorded current falls well past the noise floor, and the instrument reports no load present on either side of the open command. Only the instrument's classification contradicts the command here, so a verifier that reads the sensor values and skips the booleans accepts it. The readings are evidence; the instrument decides.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:9a2edf4a30b8ca6d3e0a227566e673acb1d61b4ba3d922141eb25f3b07210092", + "signature_b64": "lY7dYaecaKKWppo/bSLZNcsNMd7aeBLbtJVI6mprcy0kKGUxVKjAsie/CIiMh7t6yxuhBzMjeI8KUWM6/95nAQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a6c59376459616563614b4b5770706f2f62534c5a4e63734e4d64376165424c62744a5649366d70726379306b4b475578564b6a417369652f4349694d6837743679787568427a4d6a6549384b55574d362f39356e41513d3d227d", + "reason": "proof_contradiction", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "proof_close_observed_with_no_readings_and_the_load_already_present", + "note": "A close command on a circuit the instrument already reports energised establishes nothing, and this observation carries no readings at all, so the noise-floor rule cannot reach it. Without the classifier there is no rule left to refuse it.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": true, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:4bd9d9ebf4ac25d9ce4a462b6ad059ec9c98b4b4e2a2d3791ef1c4e587eeeb71", + "signature_b64": "OqdbATZq7GNNAwdkvFTvGENbbFq2XhweafljXKT42IG5SSXr7n6OeSdfDAYXrEDxBdjXyvljzqElJ8KtG6wPCg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a4f71646241545a7137474e4e4177646b7646547647454e62624671325868776561666c6a584b54343249473553535872376e364f65536466444159587245447842646a5879766c6a7a71456c4a384b744736775043673d3d227d", + "reason": "proof_contradiction", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "polarity_mismatch", + "note": "`active_high` is false, so a de-energised coil is driven by a high GPIO level. The observation records a low level for the de-energised command, which contradicts the declared driver polarity.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:04d60c08b68d923c5350266810a706bce1cd1104fccbe0f55a7c7079c27890fd", + "signature_b64": "JyKb1vOhEo9gZ3F0iUtQ+Afe3U7zers62gNy/U8mBig0u2H4hCHEy+iVgWmAkM0bdh+Cq5RuVbtNEQ23NSM1DA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a4a794b6231764f68456f39675a334630695574512b4166653355377a6572733632674e792f55386d426967307532483468434845792b695667576d416b4d306264682b43713552755662744e455132334e534d3144413d3d227d", + "reason": "proof_contradiction", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "outcomes_name_one_coil_state", + "note": "Both circuit outcomes map to `de_energised`. A coil has two states, so one of the two observations is wrong.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:1e11efd341282f5d705d7bd72f3e785e4dcc431e9a8665f4cb030dc4936d2347", + "signature_b64": "W0vWatMfpI4N9cU5udt9sDMF7rVNhwjdaTr6YWdwkEb18Qi6U+tyx4HGokeskaikvezCkR38Cyl/eqWXH4pPAg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a5730765761744d667049344e396355357564743973444d463772564e68776a6461547236595764776b45623138516936552b7479783448476f6b65736b61696b76657a436b52333843796c2f657157584834705041673d3d227d", + "reason": "mapping_contradiction", + "stage": "mapping_self_consistency", + "signature_valid": true + }, + { + "name": "terminal_state_contradicts_open_outcome", + "note": "`open_protected_circuit` is `de_energised` while `de_energised_terminal_state` is `closed`. Both cannot be observations of the same channel.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:8d69fada11ea6d4310924051f2390e482f9179327c42fd064f4461402031e944", + "signature_b64": "T+MSMjiTnlvLNNAMdZlvN5eU3KHEfW8Nu0Ib/CmYokfbzoXW2MSv2DKQFmesJEQirekevksudfF1p4SeDzX2Ag==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a542b4d534d6a69546e6c764c4e4e414d645a6c764e356555334b48456657384e753049622f436d596f6b66627a6f5857324d537632444b51466d65734a45516972656b65766b73756466463170345365447a583241673d3d227d", + "reason": "mapping_contradiction", + "stage": "mapping_self_consistency", + "signature_valid": true + }, + { + "name": "capacity_above_sensor_full_scale", + "note": "A 120 A capacity on a clamp that reads to 100 A describes a load the sensor cannot measure at all.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 120.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a3132302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:dfb6cddd460c1c1c053c569cc618649cbed271a921586df099f2d1dd0d7eb828", + "signature_b64": "kuKwi20WA0cVMaaFoiTx/LGu8lqsNffrx+cQjqMzoGdhXzE2CmxhvBQxTj5kj044UrwBpxzH4h1RSgcylAbgDw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a3132302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a6b754b7769323057413063564d6161466f6954782f4c4775386c71734e666672782b63516a714d7a6f476468587a4532436d786876425178546a356b6a3034345572774270787a4834683152536763796c41626744773d3d227d", + "reason": "out_of_bounds", + "stage": "bounds", + "signature_valid": true + }, + { + "name": "trip_point_above_sensor_full_scale", + "note": "Capacity is comfortably in range at 25 A, and the release-owned multiplier of 5.0 puts the trip point at 125 A, beyond the clamp's 100 A full scale. A saturating sensor reports the hazard as a merely high reading, so the cutoff can never fire. This is the case a capacity-only bound misses.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 25.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a32352e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:22a528df81b4a856feba6f20e4387084f7467e84e988371a5c97e6434eb9bb6b", + "signature_b64": "agCSooI2XElCeya6iZEfd5qpX/EJkRvXaiABaS7UCNC0dEML6oOqW8bA1MFVQ6hs7iMPK1oNAS+/ZMsuBtPSBA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a32352e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a616743536f6f493258456c4365796136695a456664357170582f454a6b5276586169414261533755434e433064454d4c366f4f7157386241314d46565136687337694d504b316f4e41532b2f5a4d73754274505342413d3d227d", + "reason": "out_of_bounds", + "stage": "bounds", + "signature_valid": true + }, + { + "name": "signed_by_provisioning_authority", + "note": "Genuinely signed by the provisioning authority, which is why the verdict is reachable at all: it is decided after the signature verifies, so a stranger cannot manufacture the event by naming that key over a forged signature. Refused because the commercial plane must not be able to move a trip point by raising a declared capacity.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "product-provisioning-prod", + "signing_key": "ed25519:11l5O7wTooGagnx2rbb7qKSa7gB/SfLQmS2ZuCWtLEg=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a2270726f647563742d70726f766973696f6e696e672d70726f64222c227369676e696e675f6b6579223a22656432353531393a31316c354f3777546f6f4761676e783272626237714b53613767422f53664c516d53325a754357744c45673d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:86393af69774531b357ed8d0f2e37a12b91fc8310dda96e3a8848e99600f50a4", + "signature_b64": "b+nSeO1Ye0hw5Xaevo0deEqaotpuxEQnYoDIlEERmv8oy5yEqJ4gQi9wgloQou4cPC1hq82JkgYyOmvlmwMOCw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a2270726f647563742d70726f766973696f6e696e672d70726f64222c227369676e696e675f6b6579223a22656432353531393a31316c354f3777546f6f4761676e783272626237714b53613767422f53664c516d53325a754357744c45673d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a622b6e53654f31596530687735586165766f3064654571616f7470757845516e596f44496c4545526d76386f79357945714a346751693977676c6f516f753463504331687138324a6b6759794f6d766c6d774d4f43773d3d227d", + "reason": "wrong_authority", + "stage": "authority", + "signature_valid": true + }, + { + "name": "signed_by_previous_commissioning_generation", + "note": "The previous generation is verify-only for the binding already in force. A new binding must be signed by the current generation, or a compromised key would keep authoring bindings after rotation.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:xoImN8fTEOxXYnvgC6JZ0lN0n0qvZERwz/vlOjX3MkI=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a786f496d4e386654454f7858596e766743364a5a306c4e306e3071765a4552777a2f766c4f6a58334d6b493d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:379bbe029c5d843180abe8cff5bb3d277767313e20af11261c23b484c534c588", + "signature_b64": "Ts6qjZlub1DUhlJfi4+QyWoNJWsnFYwvrtKubiH5fqiJ6bQoFEh9AQn7Ow1xbeUx4bUQJjp7OWPFIxh1escfDA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a786f496d4e386654454f7858596e766743364a5a306c4e306e3071765a4552777a2f766c4f6a58334d6b493d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a547336716a5a6c7562314455686c4a6669342b5179576f4e4a57736e4659777672744b75626948356671694a3662516f4645683941516e374f77317862655578346255514a6a70374f575046497868316573636644413d3d227d", + "reason": "superseded_signer", + "stage": "authority", + "signature_valid": true + }, + { + "name": "signing_key_is_not_a_commissioning_generation", + "note": "Self-consistent - the document names the key that signed it - and that key is neither generation of the commissioning anchor.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:My6+jSfLcyOzpAHBwTtd1kvMwOEOzaHCtdEaA3eaheU=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a4d79362b6a53664c63794f7a7041484277547464316b764d774f454f7a61484374644561413365616865553d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:f6a83d2c125a1f5b16280b60dd2ade604309aa798cc8cd0e4b5ed94b7ef8b676", + "signature_b64": "9mADH9ETMzYN7iTASa/Yes9BIQWlJlYvcJFBeHLupZcw3EvMf5g0zJcLkdA1uQs4CxEo7ei4U3Oy34X3m9QkDA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a4d79362b6a53664c63794f7a7041484277547464316b764d774f454f7a61484374644561413365616865553d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a396d4144483945544d7a594e3769544153612f59657339424951576c4a6c5976634a464265484c75705a63773345764d663567307a4a634c6b644131755173344378456f3765693455334f79333458336d39516b44413d3d227d", + "reason": "unknown_signer", + "stage": "key_selection", + "signature_valid": true + }, + { + "name": "anchors_are_identical_key_material", + "note": "Both configured anchors are the same 32 bytes, so `wrong_authority` could never be reached and the separation the contract rests on does not exist. Refused at configuration load, before any document is verified.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "accepted_binding_seq": 0, + "accepted_binding_hash": null, + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "signature_b64": "rIduw/4kEkG2P37R51vFXmNo/wYXQT/IorkRlkTLtFbt6zO44w6msHojREDx+UK18hQQ+hXmAbFTJpp3fTJHDg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a72496475772f346b456b47325033375235317646586d4e6f2f77595851542f496f726b526c6b544c74466274367a4f343477366d73486f6a524544782b554b31386851512b68586d416246544a70703366544a4844673d3d227d", + "reason": "anchor_collision", + "stage": "key_selection", + "signature_valid": true + }, + { + "name": "replayed_binding_seq", + "note": "`binding_seq` does not strictly exceed the accepted one.", + "binding": { + "v": 1, + "binding_seq": 1, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": null, + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "signature_b64": "rIduw/4kEkG2P37R51vFXmNo/wYXQT/IorkRlkTLtFbt6zO44w6msHojREDx+UK18hQQ+hXmAbFTJpp3fTJHDg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a72496475772f346b456b47325033375235317646586d4e6f2f77595851542f496f726b526c6b544c74466274367a4f343477366d73486f6a524544782b554b31386851512b68586d416246544a70703366544a4844673d3d227d", + "reason": "stale", + "stage": "freshness", + "signature_valid": true + }, + { + "name": "supersedes_does_not_match_accepted", + "note": "`binding_seq` advances but `supersedes` names a document that is not the one in force, so the chain does not connect.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:0000000000000000000000000000000000000000000000000000000000000000", + "actor": "installer:ade", + "reason": "initial commissioning", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0 + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a30303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:d25b085197f3d03c876a6a0cff99c075a870fd399f14737787b997f5e017e288", + "signature_b64": "wjGVbHLwSfYd0Xvt+TApOfC7PPkxyq75HYIiceOAecgLB4C30q3dViBiRjny/AOVDF8CDWp4GFdTnqp0yRydAQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a30303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a776a475662484c7753665964305876742b5441704f66433750506b78797137354859496963654f416563674c423443333071336456694269526a6e792f414f564446384344577034474664546e7170307952796441513d3d227d", + "reason": "stale", + "stage": "freshness", + "signature_valid": true + }, + { + "name": "polarity_revised_without_a_fresh_control_proof", + "note": "The revision inverts the driver stage and redoes the circuit leg, but carries the control proof performed against the old polarity. That proof recorded which level drove which coil state on the previous stage; under the new one it asserts the opposite. Accepting it would bring the zone into force with the polarity established by a measurement taken on the wiring it replaced -- the unproven-polarity actuation the control leg exists to close, reached through a revision rather than a first commissioning. The circuit leg is fresh, so the verdict is decided by the control leg alone.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "driver board replaced; the stage inverts", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2264726976657220626f617264207265706c616365643b2074686520737461676520696e7665727473222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:71ed5d0bee72221ee384cb1331fa6381d63c78df3649e49ac3d559f5fddd10bd", + "signature_b64": "PMdX660f7C0CAN6TvMbXNGlz9XMlnHkdpCjU7nBOK6e4EDCPYK6CyjnWX9wFj+kb8E6C3e4r+owEr+7t/0OPBQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2264726976657220626f617264207265706c616365643b2074686520737461676520696e7665727473222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a504d64583636306637433043414e3654764d62584e476c7a39584d6c6e486b6470436a55376e424f4b36653445444350594b3643796a6e57583977466a2b6b6238453643336534722b6f7745722b37742f304f5042513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_rebound_without_fresh_proof", + "note": "The revision binds the zone to a different declared clamp and carries both proof legs unchanged. Actuator identity, mapping and `calibration_ref` are exactly as retained, so the verdict is decided by the sensor alone. A proof records that this sensor observes this circuit; carried onto another sensor it asserts an association nobody observed, which is the transposition a proof exists to catch, reached through a revision rather than a first commissioning.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "clamp moved to the feeder input", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-feeder", + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d70206d6f76656420746f207468652066656564657220696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:8f708eb4613cbfa132c32055a7f2db0d301771fddbc35e39f020b6b99354c233", + "signature_b64": "46k9GaIRkgakGLDuGK8U4fpHxerNzl3839yq1dwquuF9u24QZUc4qp0+5RA4Inf01Oik0nVOhlYBdPIYdT0FCg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d70206d6f76656420746f207468652066656564657220696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a34366b39476149526b67616b474c4475474b3855346670487865724e7a6c3338333979713164777175754639753234515a5563347170302b35524134496e6630314f696b306e564f686c5942645049596454304643673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "zone_renamed_without_fresh_proof", + "note": "The revision inverts the driver stage and gives the zone a new name, carrying both proof legs from the retained record. Renaming a zone does not make its actuator new: the revision is compared against every retained zone sharing its zone id, its actuator identity or its sensor, and the retained zone on this pin was proven at the other polarity. Matching on the name alone would let a rename carry an unproven polarity into force.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "driver board replaced; zone renamed", + "zones": [ + { + "zone_id": "main-distribution-renamed", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2264726976657220626f617264207265706c616365643b207a6f6e652072656e616d6564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e2d72656e616d6564227d5d7d", + "canonical_sha256": "sha256:d33b987dba334da5b436429a7017be219ca174983d46d56b7cf8e3cfaae5d2c7", + "signature_b64": "Z7dQYR0+QcXD0n7AX37PB4HHtXWEIWaOD+YcHvJptiChAIfApVj9SrD2PhXpBEMHZ6tJ0+Hsx73Siz99yPT/Cw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2264726976657220626f617264207265706c616365643b207a6f6e652072656e616d6564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e2d72656e616d6564227d5d7d2c227369676e6174757265223a22656432353531393a5a3764515952302b51635844306e37415833375042344848745857454957614f442b596348764a70746943684149664170566a39537244325068587042454d485a36744a302b487378373353697a39397950542f43773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "zone_renamed_keeping_only_its_pin", + "note": "The revision renames the zone, binds it to a different clamp and inverts the driver stage, keeping only the pin, and carries both proof legs. Its name, its sensor and its identity as a whole match no retained zone; only its pin does, so only a consumer that compares a GPIO actuator by its pin refuses it. The retained proof observed the old clamp at the other polarity.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "zone renamed; clamp moved to the feeder input; stage inverts", + "zones": [ + { + "zone_id": "feeder-circuit", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-feeder" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d65643b20636c616d70206d6f76656420746f207468652066656564657220696e7075743b20737461676520696e7665727473222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226665656465722d63697263756974227d5d7d", + "canonical_sha256": "sha256:dc5a905200678bf73a0f654ee1e650f4395dffa521bcf6146421650f3262eb70", + "signature_b64": "4iiPjm4UdNxmGcan3KkwIfKZ4CBPX2TtLNHliZfcyvTpeq9dGJrg8uc4hY/3PBdRcjSXtVPvk3ViwElneG4uCg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d65643b20636c616d70206d6f76656420746f207468652066656564657220696e7075743b20737461676520696e7665727473222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226665656465722d63697263756974227d5d7d2c227369676e6174757265223a22656432353531393a346969506a6d3455644e786d4763616e334b6b7749664b5a34434250583254744c4e486c695a66637976547065713964474a72673875633468592f3350426452636a5358745650766b33566977456c6e6547347543673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "zone_moved_keeping_only_its_name", + "note": "The revision keeps the zone's name and moves it to another pin and another clamp, carrying both proof legs. Its actuator and its sensor match no retained zone; only its name does, so only a consumer that finds the retained zone by its name refuses it. The retained proof was taken on hardware this zone no longer uses.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor moved to pin 19; clamp moved to the feeder input", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-feeder" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72206d6f76656420746f2070696e2031393b20636c616d70206d6f76656420746f207468652066656564657220696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:5e5e89945205dff9817c653488512e05d839376542527c3ee15787cf583b8c0b", + "signature_b64": "0d2GzXbobdqvI9InEXmsVFbVCGjkFWidPjurwdjHQB+vNXSlzvX1x8XrhpgjF3iSjnn8GcJyj2uf6W+WvEoxBA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72206d6f76656420746f2070696e2031393b20636c616d70206d6f76656420746f207468652066656564657220696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a306432477a58626f626471764939496e45586d735646625643476a6b46576964506a757277646a4851422b764e58536c7a765831783858726870676a463369536a6e6e3847634a796a32756636572b5776456f7842413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "mapping_rewired_without_fresh_proof", + "note": "The revision keeps the zone's name, pin, polarity and clamp, and records the contactor rewired so that the energised coil now opens the circuit, carrying both proof legs. Only the mapping changed, so the verdict is decided by it alone. The retained proof established the opposite mapping; carried onto this one it asserts the outcome a trip would command without anyone having observed it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired to its other contact", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420746f20697473206f7468657220636f6e74616374222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:d3cbb8dc6ee2667791d19d3bda0381f02c7ab6d452d6b891c74944575fffa191", + "signature_b64": "HSH5Vsk3PE+GCgdOxmFg8WF+rMFmvpYIwvY00b3WbDfRTCcdqp5IaxTCRvI9wrajZgyPKtanNDuj3f10C091Cw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420746f20697473206f7468657220636f6e74616374222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a4853483556736b3350452b474367644f786d46673857462b724d466d76705949777659303062335762446652544363647170354961785443527649397772616a5a6779504b74616e4e44756a336631304330393143773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "zone_held_to_every_retained_zone_it_matches", + "note": "The revision keeps the zone's name, moves it to pin 13 and takes the clamp of another retained zone. It matches three retained zones: its own by name, the feeder by sensor, and the zone on pin 13 by pin. Its fresh legs follow its own zone's proof and pin 13's, but not the feeder's, which was proven later. A consumer that checks only the first match, the last, or stops at the first that passes accepts it; the rule holds the zone to every match, and the feeder's proof refuses it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor moved to pin 13; clamp taken from the feeder zone", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 13, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-feeder" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 13, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000000000 + }, + "feeder": { + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000900000, + "control_proof_at_ms": 1800000900000 + }, + "pin-13": { + "identity": { + "gpio_pin": 13, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-spare", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72206d6f76656420746f2070696e2031333b20636c616d702074616b656e2066726f6d2074686520666565646572207a6f6e65222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31337d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:d85c6f5471b0a60b2363a8b119e9ce3a358f8e50d746d9f592bc591ad20980ad", + "signature_b64": "6N5uDMyh/mVu/3JuvU7uJmC7E/r/P1HgZEHA15FVMeWxCSA+gXYB7peQohq1xijq4+cviHRrdTVUOkCm7a99Cg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72206d6f76656420746f2070696e2031333b20636c616d702074616b656e2066726f6d2074686520666565646572207a6f6e65222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31337d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a364e3575444d79682f6d56752f334a75765537754a6d4337452f722f503148675a454841313546564d6557784353412b67585942377065516f68713178696a71342b637669485272645456554f6b436d3761393943673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "mapping_rewired_carrying_its_control_leg", + "note": "The mapping is rewired and the circuit leg is redone, but the control leg is carried from the retained record. The control leg recorded which level drove which coil state under the old mapping; any change needs both legs refreshed, not only a change to the actuator, so the verdict is decided by the control leg alone.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired; circuit re-proven, control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636972637569742072652d70726f76656e2c20636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:ea2314ec4c880413fb5a9920746e0ad49ee0a4833a8987fed6748f02956c2201", + "signature_b64": "WQnvhrjzgxAikoW9v2CA3yjX3b1y/M1eQnLbPPUNTYymCfVgP3X/AP5s0no/z0yevQIp0oYIi6CFOcc6eh06BA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636972637569742072652d70726f76656e2c20636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a57516e7668726a7a677841696b6f57397632434133796a58336231792f4d3165516e4c625050554e5459796d436656675033582f41503573306e6f2f7a30796576514970306f5949693643464f6363366568303642413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "firmware_board_replaced_without_fresh_proof", + "note": "The firmware zone keeps its name and clamp and moves to a new board on the same channel, carrying its proof. A firmware actuator is its board and its channel together, so the identity changed and the proof taken on the old board does not carry.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "actor": "installer:ade", + "reason": "pump relay board replaced", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-0d4e1a77", + "channel": "relay0" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-0d4e1a77", + "channel": "relay0" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000 + }, + "borehole-pump": { + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d702072656c617920626f617264207265706c61636564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3064346531613737227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:54ed7b9fd1358d178d15582c98ce12680264b26314c718e81852b5f4f5d78e8b", + "signature_b64": "5fTXVu9CovW1hmN/y4anISzKSMovzqMQrqBF/c0U2FaCk1WvFA8rZX/ibacY1/b7lAPe3w+1fWuVwVb80HjqAQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d702072656c617920626f617264207265706c61636564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3064346531613737227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a35665458567539436f765731686d4e2f7934616e49537a4b534d6f767a714d51727142462f633055324661436b315776464138725a582f6962616359312f62376c41506533772b31665775567756623830486a7141513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "zone_found_by_sensor_id_not_by_the_whole_sensor", + "note": "The revision renames the zone, moves it to pin 19 and recalibrates the clamp, carrying both proof legs. Only the `sensor_id` links it to the retained zone; the sensor as a whole differs. A consumer that finds a retained zone by the whole sensor finds nothing and accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "zone renamed onto pin 19; clamp recalibrated", + "zones": [ + { + "zone_id": "main-on-19", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current_rms", + "unit": "amp_rms", + "range_min": 0.0, + "range_max": 200.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.07, + "calibration_ref": "sct013-100-2026-09-01-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d6564206f6e746f2070696e2031393b20636c616d7020726563616c69627261746564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3230302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d705f726d73227d2c227a6f6e655f6964223a226d61696e2d6f6e2d3139227d5d7d", + "canonical_sha256": "sha256:c63b2f31d5c081dabb8382b394f4431718c03762553d42ff5e76c5aa108665fe", + "signature_b64": "twY79a4O8SrL5SGkCkvag9rTvWuVjcDTvfDSa+CLwa1eGTr6Yka8NeaLV/SEgpODSPzTbOl4aeXQV6BAfflWCQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d6564206f6e746f2070696e2031393b20636c616d7020726563616c69627261746564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3230302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d705f726d73227d2c227a6f6e655f6964223a226d61696e2d6f6e2d3139227d5d7d2c227369676e6174757265223a22656432353531393a747759373961344f3853724c3553476b436b766167397254765775566a63445476664453612b434c7761316547547236596b61384e65614c562f534567704f4453507a54624f6c34616558515636424166666c5743513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "circuit_leg_carried_behind_a_fresh_control_leg", + "note": "The mapping is rewired and the control leg redone, but the circuit leg is carried. A fresh control leg says the pin still moves the coil; it says nothing about what the coil now does to the circuit, so the carried circuit leg decides the case alone.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired; control leg redone, circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636f6e74726f6c206c6567207265646f6e652c2063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:4d57c939f8ea157dec9a548bf2a165fc87b026d0bb785be6c1232733952f7073", + "signature_b64": "ss9hivVk3vKB7BSUjOuoI9CAZWJ7M8+AmNmdwJ+eeKoYGE6DXGycQClwAwMPTlskieGqH62hOpQEMYmDaIxJAQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636f6e74726f6c206c6567207265646f6e652c2063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a737339686976566b33764b42374253556a4f756f493943415a574a374d382b416d4e6d64774a2b65654b6f59474536445847796351436c7741774d50546c736b69654771483632684f7051454d596d446149784a41513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_changed_carrying_its_control_leg", + "note": "Only the sensor changes, by its noise floor, and the circuit leg is redone, but the control leg is carried. Freshness is required of every claimed leg whichever field changed, so the control leg decides it; a consumer that refreshed the control leg only for an actuator or mapping change, or that noticed only a new sensor_id or calibration, accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "clamp noise floor re-measured; circuit re-proven", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.07, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d70206e6f69736520666c6f6f722072652d6d656173757265643b20636972637569742072652d70726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:fd3f5c53a0b2ffb69022634dc3464b2e1b781ea3ef36283ffbfb7dfe54c3032c", + "signature_b64": "dvI7I1Nhm58+xBSIwcEXiVDjeZAgF2ZsaMaj8N4TUtGd7jThdSFps0Yg1g2iK8Ra8SwnYRY9uugo9d38H9f0Bw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d70206e6f69736520666c6f6f722072652d6d656173757265643b20636972637569742072652d70726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6476493749314e686d35382b78425349776345586956446a655a416746325a73614d616a384e345455744764376a54686453467073305967316732694b3852613853776e595259397575676f396433384839663042773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "control_leg_carried_behind_an_unclaimed_circuit_leg", + "note": "The circuit leg is left undemonstrated, which holds it to no time, but the control leg is claimed and carried from the retained record. An unclaimed circuit leg does not excuse a claimed control leg, which is held to its retained time and refuses the case.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired; circuit not yet proven, control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "undemonstrated", + "performed_at_ms": 1800000000000, + "reason": "rewired; circuit proof to follow", + "observations": [], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "development", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b2063697263756974206e6f74207965742070726f76656e2c20636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22726577697265643b20636972637569742070726f6f6620746f20666f6c6c6f77227d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:ed107b2e4071c0a822b55eb01d61cf57a5b3df6ac256944e794b2e135f5a9f26", + "signature_b64": "nVRZ9w/lrO2Ksrs07KcVH4SLBeyCzubi1jiv00ObLet8Gj1rTrs/gblqpRMlkKYoUZ6VoH5TwxQNT/555XkPBQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b2063697263756974206e6f74207965742070726f76656e2c20636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22726577697265643b20636972637569742070726f6f6620746f20666f6c6c6f77227d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6e56525a39772f6c724f324b73727330374b63564834534c426579437a756269316a697630304f624c657438476a31725472732f67626c7170524d6c6b4b596f555a36566f4835547778514e542f353535586b5042513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "firmware_channel_moved_without_fresh_proof", + "note": "The firmware zone keeps its name, clamp and board and moves to the board's other channel, carrying its proof. A firmware actuator is its board and its channel together, so the identity changed and the proof taken on the old channel does not carry.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "actor": "installer:ade", + "reason": "pump moved to the board's second relay", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + }, + { + "zone_id": "borehole-pump", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 4.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "actuator": { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay1" + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 2.1, + "sensor_after": 0.01, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.01, + "sensor_after": 2.1, + "terminal_state_observed": "closed" + } + ] + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-pump" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + }, + { + "kind": "firmware_channel", + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay1" + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000 + }, + "borehole-pump": { + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70206d6f76656420746f2074686520626f6172642773207365636f6e642072656c6179222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617931222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:8935dcd71e89303763bc42213965b0fb6225f3dc8362a1d7448c769c15b8fa33", + "signature_b64": "YEa8FUMJk4hrxs6B83OxWJNBNiCeoxeCmnMhmh7j4tkPkl86Mwhv2ZhH6i321Pr3y9/1QTFPvlw9mK6OJkPNDA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70206d6f76656420746f2074686520626f6172642773207365636f6e642072656c6179222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617931222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a5945613846554d4a6b3468727873364238334f78574a4e424e6943656f7865436d6e4d686d68376a34746b506b6c38364d776876325a6848366933323150723379392f3151544650766c77396d4b364f4a6b504e44413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "name_taken_from_a_retained_zone", + "note": "The revision keeps the main circuit's hardware exactly and renames it to `feeder`, the name of another retained zone proven on pin 19. Against its own hardware nothing changed; against `feeder`, whose name it takes, everything did, and its circuit leg is no later than `feeder`'s proof. A rename onto a retained zone's name is held to that zone. A consumer that stopped at the unchanged match, preferred the hardware match, looked only at the latest proof, or checked the circuit leg only on a single match accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "main circuit renamed to feeder; the old feeder zone is retired", + "zones": [ + { + "zone_id": "feeder", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000900000, + "control_proof_at_ms": 1800000000000 + }, + "feeder": { + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e20636972637569742072656e616d656420746f206665656465723b20746865206f6c6420666565646572207a6f6e652069732072657469726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22666565646572227d5d7d", + "canonical_sha256": "sha256:65fbf548ceeb3a79e35aeaa6383903e76625048b9838fd536d354f68f1d61ccf", + "signature_b64": "MFwbUm34ajEt/e4iESX4qp5UvsZeWhBZ9mYgRm09KSQSlLYgHUfotb3brPRw40s3n1EUTTnMHO9Cp9uy4gWIBw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e20636972637569742072656e616d656420746f206665656465723b20746865206f6c6420666565646572207a6f6e652069732072657469726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22666565646572227d5d7d2c227369676e6174757265223a22656432353531393a4d467762556d3334616a45742f653469455358347170355576735a655768425a396d5967526d30394b5351536c4c59674855666f7462336272505277343073336e31455554546e4d484f3943703975793467574942773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "recalibrated_without_fresh_proof", + "note": "The revision changes only the sensor's `calibration_ref`, a new calibration, and carries both proof legs. Every sensor field is part of what the proof established, so a consumer that compared the sensor without `calibration_ref` accepts a proof taken on a sensor described otherwise.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "sensor calibration_ref redeclared", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-09-01-b" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f722063616c6962726174696f6e5f7265662072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:a868bbfec69daa6eee93f8c69065b3fc2c3fdfa52b8369421ecc0bf443d69a52", + "signature_b64": "wvoioYVAQMPrPOw+5B6Ds+JiqbZKKqfYiECP5tRdb1HMxKu9NceFTvkJbLFEemiBstzipV+ph8LmBXSY2pVSDQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f722063616c6962726174696f6e5f7265662072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a77766f696f595641514d5072504f772b35423644732b4a6971625a4b4b71665969454350357452646231484d784b75394e63654654766b4a624c4645656d694273747a6970562b7068384c6d425853593270565344513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_range_redeclared_without_fresh_proof", + "note": "The revision changes only the sensor's `range_max`, a new upper range, and carries both proof legs. Every sensor field is part of what the proof established, so a consumer that compared the sensor without `range_max` accepts a proof taken on a sensor described otherwise.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "sensor range_max redeclared", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 150.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f722072616e67655f6d61782072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:724a2a79c77b56e6db2bea712b41bd402bd4ac36a3745c69c571f2a0b2fd397b", + "signature_b64": "MlYDa+42P2dcp7QBts+tMJGu3Wb5o4ZKhlmZhvuSYbpYc40OrBUlRtKwxM/G5hUKSk6dmRnuhJpiBiMPpnvBBA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f722072616e67655f6d61782072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a4d6c5944612b3432503264637037514274732b744d4a4775335762356f345a4b686c6d5a68767553596270596334304f7242556c52744b77784d2f473568554b536b36646d526e75684a706942694d50706e764242413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_lower_range_redeclared_without_fresh_proof", + "note": "The revision changes only the sensor's `range_min`, a new lower range, and carries both proof legs. Every sensor field is part of what the proof established, so a consumer that compared the sensor without `range_min` accepts a proof taken on a sensor described otherwise.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "sensor range_min redeclared", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 1.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f722072616e67655f6d696e2072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:5c91f0adeb302e5a6ea8a46cfb5d067257c0e47a3952a96ec23eed9e7b22f79f", + "signature_b64": "SsLfBOaGENLkXcBWsScib3nc2IWB69h6BjF1yI7DWrsDmvAck/LYvEU2io8h89uDxVf4NpnD0cfh6CUW1LO5Cg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f722072616e67655f6d696e2072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a53734c66424f6147454e4c6b586342577353636962336e633249574236396836426a463179493744577273446d7641636b2f4c5976455532696f386838397544785666344e706e443063666836435557314c4f3543673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_unit_redeclared_without_fresh_proof", + "note": "The revision changes only the sensor's `unit`, a new unit, and carries both proof legs. Every sensor field is part of what the proof established, so a consumer that compared the sensor without `unit` accepts a proof taken on a sensor described otherwise.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "sensor unit redeclared", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "amp", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f7220756e69742072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:202a1e028896e4321d59705d19a7c0b3f4bbb72c492786c66469a409ed91e5da", + "signature_b64": "OEqsZuRisAGcjNwdwEEAc6Z+VkjjK/6xhLWPz1CxEy3GbmndZo9cY2+hm4CAmCtjkSRJIex3gZ6DjwRB32RGAw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f7220756e69742072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a4f4571735a755269734147636a4e77647745454163365a2b566b6a6a4b2f3678684c57507a31437845793347626d6e645a6f396359322b686d3443416d43746a6b53524a49657833675a36446a7752423332524741773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_direction_flipped_without_fresh_proof", + "note": "The revision changes only the sensor's `direction`, a reversed clamp, and carries both proof legs. Every sensor field is part of what the proof established, so a consumer that compared the sensor without `direction` accepts a proof taken on a sensor described otherwise.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "sensor direction redeclared", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "negative_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f7220646972656374696f6e2072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:311d2eca531fe6ea0f13021556524648b331c8d00cdf4c8c730544c7919d85b9", + "signature_b64": "pHJ1JFJssh+ZYOMD3aawidtFtF0HEKwKyqDVy1cKeCle7EkLJZEMQJ/H9kF1PkRkWLtwtjgp/kaGYcJDj7JiAA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f7220646972656374696f6e2072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a70484a314a464a7373682b5a594f4d44336161776964744674463048454b774b797144567931634b65436c6537456b4c4a5a454d514a2f48396b4631506b526b574c7477746a67702f6b614759634a446a374a6941413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_quantity_redeclared_without_fresh_proof", + "note": "The revision changes only the sensor's `quantity`, a new quantity, and carries both proof legs. Every sensor field is part of what the proof established, so a consumer that compared the sensor without `quantity` accepts a proof taken on a sensor described otherwise.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "sensor quantity redeclared", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current_rms", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f72207175616e746974792072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:43b361737c1ef65f51a81941fc6b1bd75fe0cbdc0ce5b487a50429b101bd3508", + "signature_b64": "z9kWmj4jACmmzmhK1byP/+HCcEja2svZ0wfhfQJAGKH9P/eKo1XIvWidrHrlJVK9PJ0wXTDLmchVyp3/ZHVkDQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2273656e736f72207175616e746974792072656465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a7a396b576d6a346a41436d6d7a6d684b316279502f2b484363456a613273765a3077666866514a41474b4839502f654b6f315849765769647248726c4a564b39504a30775854444c6d6368567970332f5a48566b44513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "retained_zone_held_by_every_revision_zone_matching_it", + "note": "Two revision zones match the one retained zone: the first takes its name on a new pin with fresh legs, the second keeps its pin and clamp under a new name, inverts the polarity and carries the proof. Each revision zone is held to every retained zone it matches, so the second is refused; a consumer that let each retained zone match only one revision zone gives it to the first and accepts the carried proof.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "main moved to pin 19; its old contactor reused as a new zone", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + }, + { + "zone_id": "main-renamed", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-feeder", + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + }, + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e206d6f76656420746f2070696e2031393b20697473206f6c6420636f6e746163746f72207265757365642061732061206e6577207a6f6e65222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d72656e616d6564227d5d7d", + "canonical_sha256": "sha256:45529e094c761544744a30ca535d86089516a1f559d20366a520ca267f15abc7", + "signature_b64": "r5Mb/SiYasSpXxJP8hNBTkaA0qg8gjPnmZ4cOoiF6/aOjCKg3lmLLK8XWXGAos78yJ4oNpOvRTwXmZlTIVfPDw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e206d6f76656420746f2070696e2031393b20697473206f6c6420636f6e746163746f72207265757365642061732061206e6577207a6f6e65222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d72656e616d6564227d5d7d2c227369676e6174757265223a22656432353531393a72354d622f5369596173537058784a5038684e42546b614130716738676a506e6d5a34634f6f6946362f614f6a434b67336c6d4c4c4b3858575847416f733738794a346f4e704f76525477586d5a6c544956665044773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "control_leg_stale_against_one_of_several_matches", + "note": "The zone is matched by two retained zones, one by its pin and one by its name. Its circuit leg is fresh against both and its control leg is fresh against the second but no later than the first's control proof. A consumer that checked the control leg only when a single retained zone matched accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "renamed to feeder on pin 26 with a spare clamp", + "zones": [ + { + "zone_id": "feeder", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-spare", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-spare" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000900000 + }, + "feeder": { + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272656e616d656420746f20666565646572206f6e2070696e2032362077697468206120737061726520636c616d70222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d7370617265222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22666565646572227d5d7d", + "canonical_sha256": "sha256:c7eb5aa4846e091310e12cbe93e49da11e0227e57d04a280777a106db3ed0fa2", + "signature_b64": "82DBi1jUHEPJp3phKrusr1mc3R63s3E7fIybJFM7xKoz6D7KUsKBcQT/XJ6cXof24OJ1y1ynffJFlq2WHeAzCw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272656e616d656420746f20666565646572206f6e2070696e2032362077697468206120737061726520636c616d70222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d7370617265222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22666565646572227d5d7d2c227369676e6174757265223a22656432353531393a3832444269316a554845504a703370684b72757372316d633352363373334537664979624a464d37784b6f7a3644374b55734b426351542f584a3663586f6632344f4a317931796e66664a466c7132574865417a43773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "circuit_leg_carried_behind_an_undemonstrated_control_leg", + "note": "The mapping is rewired, the control leg is left undemonstrated and the circuit leg is carried. An unclaimed control leg does not excuse a claimed circuit leg, which is held to its retained time and refuses the case.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired; circuit carried, control leg to follow", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "undemonstrated", + "performed_at_ms": 1800000900000, + "reason": "control leg to follow", + "observations": [] + } + } + } + ] + }, + "expected_state": "provisional", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b206369726375697420636172726965642c20636f6e74726f6c206c656720746f20666f6c6c6f77222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030302c22726561736f6e223a22636f6e74726f6c206c656720746f20666f6c6c6f77227d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:814779b7ba877614dae5b9afcb9cdc664ec990e41a42a76e99df05f425f4c581", + "signature_b64": "xJpBv+VPbI2IvpmsD7TGBgRFj9zxmg997Msmrq0aaQ58w+SsZ/UKsw/XdErKRn1WVZckAzlJdwcoGYNDBfxiDg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b206369726375697420636172726965642c20636f6e74726f6c206c656720746f20666f6c6c6f77222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22756e64656d6f6e73747261746564222c226f62736572766174696f6e73223a5b5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030302c22726561736f6e223a22636f6e74726f6c206c656720746f20666f6c6c6f77227d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a784a7042762b56506249324976706d7344375447426752466a397a786d673939374d736d7271306161513538772b53735a2f554b73772f586445724b526e3157565a636b417a6c4a6477636f47594e444266786944673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "pre_energisation_leg_carried_without_fresh_proof", + "note": "The clamp is recalibrated and the control leg redone, but the circuit leg is a pre_energisation proof carried from the retained record. A meter proof is a claimed leg like an actuation proof, held to the retained time; a consumer that counted only actuate_and_observe as claimed exempts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "clamp recalibrated; control leg redone, meter proof carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-09-01-c" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "pre_energisation", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "load_present_before": true, + "load_present_after": false, + "terminal_state_observed": "open", + "instrument": "multimeter_continuity" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "load_present_before": false, + "load_present_after": true, + "terminal_state_observed": "closed", + "instrument": "multimeter_continuity" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d7020726563616c696272617465643b20636f6e74726f6c206c6567207265646f6e652c206d657465722070726f6f662063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a227072655f656e65726769736174696f6e222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d63222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:90b6d2c1bde26973afeb1abacaf5ef58c1bb6c9d1be91a7620d27bc14f431691", + "signature_b64": "3/1Ju4zZ0+67WGMr5vM2Qvl0eufvc49KKA/sukWgFpEXQ4FCusLAmdtOuqwxokH2xPCmv0JOt4Ti4n2rqRF0Aw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d7020726563616c696272617465643b20636f6e74726f6c206c6567207265646f6e652c206d657465722070726f6f662063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a227072655f656e65726769736174696f6e222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d63222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a332f314a75347a5a302b363757474d7235764d3251766c30657566766334394b4b412f73756b5767467045585134464375734c416d64744f757177786f6b48327850436d76304a4f74345469346e32727152463041773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "circuit_leg_held_to_its_own_retained_time_not_the_earlier", + "note": "The retained control proof predates the retained circuit proof. Both new legs fall between them: the control leg is fresh, the circuit leg is not. Each leg is held to the retained time of the same leg, so the circuit leg refuses it; a consumer that held the circuit leg to the earlier of the two retained times accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired and both legs proven", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000300000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000300000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000600000, + "control_proof_at_ms": 1800000000000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:daf302d6d76fed5a24a964199e37912fc300803889bc1a68e764b155fdfdba68", + "signature_b64": "MRRNxdXRwz96553w6vMGwiEHEsvbkJkn6UsZuUIFNlszhx7bkR03dko5+kONOpWpI1LDjkUyRfMSZNvji9mnAQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f72207265776972656420616e6420626f7468206c6567732070726f76656e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303330303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a4d52524e78645852777a39363535337736764d4777694548457376626b4a6b6e3655735a755549464e6c737a687837626b523033646b6f352b6b4f4e4f70577049314c446a6b557952664d535a4e766a69396d6e41513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "active_high_changed_with_only_the_circuit_leg_carried", + "note": "Only `active_high` changes. The other leg is redone and the circuit leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `active_high`; a consumer that exempted the circuit leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "active_high changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226163746976655f68696768206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:c8dd62787068f06cc06be80cb2da1a3728d37a1252361893fe00e42b4841879f", + "signature_b64": "rnFEem34e/Ke1m0m0zqhadb2RDbg3Q54FhZnIvHs6398YKdIeUAFsz1HRSTaZ8OhKj++PLkHAS3jXwOVmIU3Cg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226163746976655f68696768206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a726e4645656d3334652f4b65316d306d307a716861646232524462673351353446685a6e4976487336333938594b644965554146737a3148525354615a384f684b6a2b2b504c6b484153336a58774f566d49553343673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "quantity_changed_with_only_the_circuit_leg_carried", + "note": "Only `quantity` changes. The other leg is redone and the circuit leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `quantity`; a consumer that exempted the circuit leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "quantity changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current_rms", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227175616e74697479206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:f4b503e884b6840e18e789b403fdbb1b684614e00363b9e2ac8e4b70007edcb2", + "signature_b64": "/1h23OkH0UQ+9hdOgx9PbnPb5wnnBJA/jbDPnWj9YanUo9i/G3O0C44iRcwAlXhj+V1nAUUYMbx3FVQ9wsurDw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227175616e74697479206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a2f316832334f6b483055512b3968644f67783950626e506235776e6e424a412f6a6244506e576a3959616e556f39692f47334f3043343469526377416c58686a2b56316e415555594d627833465651397773757244773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "unit_changed_with_only_the_circuit_leg_carried", + "note": "Only `unit` changes. The other leg is redone and the circuit leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `unit`; a consumer that exempted the circuit leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "unit changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "amp", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22756e6974206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:98521ae7a7a1ec9ba504b1e275bbc5d0cc5e3fdb744e99b06c39bc5c3d0ce84f", + "signature_b64": "8ZVvvxzmBDZ7Z2ZQ0PEvQBR4bLA5jdMpgfsJ+azBpnKcf4MxqRj9tQN4bsNeQQR9Yo3kfve4mwbzUTTAx3vNAw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22756e6974206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a385a567676787a6d42445a375a325a513050457651425234624c41356a644d706766734a2b617a42706e4b6366344d7871526a3974514e3462734e6551515239596f336b667665346d77627a555454417833764e41773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "range_min_changed_with_only_the_circuit_leg_carried", + "note": "Only `range_min` changes. The other leg is redone and the circuit leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `range_min`; a consumer that exempted the circuit leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "range_min changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 1.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d696e206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:6f4b424543e51c56f2489874e3bec66c39d8e68e7db871ce0206fd5c3c1b27a0", + "signature_b64": "Fjm7Dip2p9wWD6O+zK4NJEBNAygCjQFv0HHmJBe7OV50T5+SSxkJ87TWkqnuPkeHwSUyc22H/3Q//ulZBZGeAA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d696e206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a466a6d37446970327039775744364f2b7a4b344e4a45424e417967436a5146763048486d4a4265374f56353054352b5353786b4a383754576b716e75506b654877535579633232482f33512f2f756c5a425a476541413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "range_max_changed_with_only_the_circuit_leg_carried", + "note": "Only `range_max` changes. The other leg is redone and the circuit leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `range_max`; a consumer that exempted the circuit leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "range_max changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 150.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d6178206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:7995b79261877d4c6ef4a5be56ef170679197c51e5f83d9958f0d1cf247290a4", + "signature_b64": "Aksc+wKkU0Z5xX4w+CO9if4pr5L2nVsVGy8JcTwIKjv9UQGNoY28PEAL83OmnAhxAHFs9BdGbcB0l7oxRlHXDQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d6178206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a416b73632b774b6b55305a35785834772b434f396966347072354c326e5673564779384a635477494b6a76395551474e6f5932385045414c38334f6d6e4168784148467339426447626342306c376f78526c485844513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "direction_changed_with_only_the_circuit_leg_carried", + "note": "Only `direction` changes. The other leg is redone and the circuit leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `direction`; a consumer that exempted the circuit leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "direction changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "negative_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22646972656374696f6e206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:730b1db7b51453695889fcf73b21e563e87f4b138887862772fedbe114cc0f43", + "signature_b64": "dStRuGnT24gboBIy0st+7Key2R0Iu8A/eT/UrKS4A3iOqhlvW5dJBHP5vSRf1nCF5dfAc0NEsHS/i+MvjGocCw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22646972656374696f6e206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6453745275476e54323467626f4249793073742b374b6579325230497538412f65542f55724b53344133694f71686c765735644a4248503576535266316e43463564664163304e457348532f692b4d766a476f6343773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "noise_floor_changed_with_only_the_circuit_leg_carried", + "note": "Only `noise_floor` changes. The other leg is redone and the circuit leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `noise_floor`; a consumer that exempted the circuit leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "noise_floor changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.07, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226e6f6973655f666c6f6f72206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:89928d7e06f9fd204676e15e21fe0155c9c9d7e52aba45cffbda5ad027f49125", + "signature_b64": "1UciVhFg5bhRtm6tuht2wAnEjnJ7tggZOZx/HGmEIOnzxl2jLFhItbWsyJcgEL3dmcQJWj6g/2AhCvX2nf7gDw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226e6f6973655f666c6f6f72206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a315563695668466735626852746d36747568743277416e456a6e4a377467675a4f5a782f48476d45494f6e7a786c326a4c46684974625773794a6367454c33646d63514a576a36672f324168437658326e66376744773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "gpio_pin_changed_with_only_the_control_leg_carried", + "note": "Only `gpio_pin` changes. The other leg is redone and the control leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `gpio_pin`; a consumer that exempted the control leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "gpio_pin changed; the control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226770696f5f70696e206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:9fea44109dfa01286291864f6e01cb3051cd83358a9ab7ef6dde9d573cf3cc5d", + "signature_b64": "LZ80nIBUw5dJjVX0mrDYRorza6ERS9HcaS4ufD90ZYC3yKgcAF3pK+6XnaqY2xzgxznDVDnyZnh9griz+JhfBQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226770696f5f70696e206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a4c5a38306e4942557735644a6a5658306d724459526f727a613645525339486361533475664439305a594333794b6763414633704b2b36586e61715932787a67787a6e4456446e795a6e68396772697a2b4a686642513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "quantity_changed_with_only_the_control_leg_carried", + "note": "Only `quantity` changes. The other leg is redone and the control leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `quantity`; a consumer that exempted the control leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "quantity changed; the control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current_rms", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227175616e74697479206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:b741c9ef7cade999963d63299feda12c89c58dffd9988bbc44b1dfc168a4e1ca", + "signature_b64": "+fa/bg92Cf55yObJGCwBCfg8QwRO91TjCWlr/vgjgo6Lf/Z6uluDZxl3+fVe7Bfqz6ptfqRbYXaIZQUK7MaqDw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227175616e74697479206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a2b66612f6267393243663535794f624a47437742436667385177524f3931546a43576c722f76676a676f364c662f5a36756c75445a786c332b665665374266717a36707466715262595861495a51554b374d617144773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "unit_changed_with_only_the_control_leg_carried", + "note": "Only `unit` changes. The other leg is redone and the control leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `unit`; a consumer that exempted the control leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "unit changed; the control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "amp", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22756e6974206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:53bd2ebc98e738532d4b06d3b1ff256d10d0ac32c78fd4b3dfe7202a59b41953", + "signature_b64": "jgYkgDkrno4V/nX2ljhL/rXoy4TelR0hE1qrpoMkgM//KAZfACsl7P6o5aP4qU/Ad/JYFr+LwdX25DHXVgL3Bg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22756e6974206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6a67596b67446b726e6f34562f6e58326c6a684c2f72586f793454656c52306845317172706f4d6b674d2f2f4b415a664143736c3750366f3561503471552f41642f4a5946722b4c776458323544485856674c3342673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "range_min_changed_with_only_the_control_leg_carried", + "note": "Only `range_min` changes. The other leg is redone and the control leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `range_min`; a consumer that exempted the control leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "range_min changed; the control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 1.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d696e206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:8718ecea89a1debd2a5584f8453b091dc4a654af770f45c39777824a649eb70d", + "signature_b64": "hi5ev8hrX40i3fwKCq6KlK8NSclZ+Rugl4nvXcXfSfN6XBGZRULXoG/MZ1huQuFrAl5beKYdkyDl+VO1HEapBQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d696e206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6869356576386872583430693366774b4371364b6c4b384e53636c5a2b5275676c346e765863586653664e365842475a52554c586f472f4d5a31687551754672416c3562654b59646b79446c2b564f314845617042513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "range_max_changed_with_only_the_control_leg_carried", + "note": "Only `range_max` changes. The other leg is redone and the control leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `range_max`; a consumer that exempted the control leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "range_max changed; the control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 150.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d6178206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:8e0a3d0e8261676bb486cb8833127850896e9dd5745530cbedcf6af34388766b", + "signature_b64": "t4Y4WQHH8Vgav5qggMwdrAltXKa4ixVd9OAB+WQvGjRqO5WrKXmVJgYLk9YUXhf5wpK1y/5d59MaWWqszaOdAw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2272616e67655f6d6178206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a74345934575148483856676176357167674d776472416c74584b613469785664394f41422b575176476a52714f3557724b586d564a67594c6b3959555868663577704b31792f356435394d61575771737a614f6441773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "direction_changed_with_only_the_control_leg_carried", + "note": "Only `direction` changes. The other leg is redone and the control leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `direction`; a consumer that exempted the control leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "direction changed; the control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "negative_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22646972656374696f6e206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:67cb23c8e124b98fe831da4b9ab56f11f3578cf15fc8303be9f9550c8cde562a", + "signature_b64": "h+rlvvkFA4KgHfwRG85HXTueEhcD2zJsSlAtZ87Dq3xa6D8VgiKU1xNhJB4KDdtfCtvtM15ceHrHvbXrcPczBw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22646972656374696f6e206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a682b726c76766b4641344b6748667752473835485854756545686344327a4a73536c41745a383744713378613644385667694b5531784e684a42344b44647466437476744d31356365487248766258726350637a42773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "calibration_ref_changed_with_only_the_control_leg_carried", + "note": "Only `calibration_ref` changes. The other leg is redone and the control leg is carried from the retained record. A change to any field requires every claimed leg to be fresh, not the leg a reader might pair with `calibration_ref`; a consumer that exempted the control leg for this change accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "calibration_ref changed; the control leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-09-01-d" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2263616c6962726174696f6e5f726566206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:5b2abe4a3938aae7f351d1a6596ac7dad8107b2ab1becfc23fc063988ddd8b8c", + "signature_b64": "TSRFzTbuSI6mL0PG7zORTxQZI4zUgWzoRNqV+dkn+1r9VQ9qU5zHVWRfSt7vYYic28WD9Vlx+6O5E5o1rKL2DQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2263616c6962726174696f6e5f726566206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a545352467a5462755349366d4c305047377a4f525478515a49347a5567577a6f524e71562b646b6e2b3172395651397155357a485657526653743776595969633238574439566c782b364f3545356f31724b4c3244513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_replaced_with_only_the_circuit_leg_carried", + "note": "Only `sensor_id`, `calibration_ref` change, together: a replaced clamp. The other leg is redone and the circuit leg is carried. A consumer that exempted the circuit leg for a replaced clamp accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "2 fields changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-09-01-d" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-feeder" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:31ecd685d1ad6752388f326f4c4cb538dfa5081ab6573b0feada67e72e80519c", + "signature_b64": "vUXiYJN6Gb5u2aJsvJmXEJexqlAF7oyvD1N0AO2y2YuSeDJfcqjwr4ffVyocrCOBmKJSrBQMkTYLIk3xCxi4AQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a76555869594a4e364762357532614a73764a6d58454a6578716c4146376f797644314e30414f32793259755365444a6663716a777234666656796f6372434f426d4b4a537242514d6b54594c496b33784378693441513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "actuator_replaced_with_only_the_circuit_leg_carried", + "note": "Only `gpio_pin`, `active_high` change, together: a replaced driver. The other leg is redone and the circuit leg is carried. A consumer that exempted the circuit leg for a replaced driver accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "2 fields changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": true + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:2bf52286db9f86297a8173554e228cb5b6cb65840408996852005b85d75d8228", + "signature_b64": "WbZGE79uQuJZLvGkYZvRpigaORtj9VSUQ6HWjDwxzaXaafiCssryHSUK9CtSb+IpJ0Fbu/dl8pI0EzWVJwMwBQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a57625a474537397551754a5a4c76476b595a7652706967614f52746a39565355513648576a4477787a61586161666943737372794853554b39437453622b49704a304662752f646c38704930457a57564a774d7742513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "rewired_to_another_pin_with_only_the_circuit_leg_carried", + "note": "Only `gpio_pin`, `mapping` change, together: a rewired actuator. The other leg is redone and the circuit leg is carried. A consumer that exempted the circuit leg for a rewired actuator accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "2 fields changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:0575f4c646aefcce6428aaebf7ee7f805e347aa0d38202f4a356a4a41d84a13f", + "signature_b64": "zpYdAoLUyib4QPe6jA5EgKeRPXQOTK15sHEMpXTsOFiHzFuvqSF4jixO8v200jXhDsfGN0Ecnv0+5a95WtJyBw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a7a705964416f4c5579696234515065366a413545674b65525058514f544b31357348454d705854734f4669487a467576715346346a69784f38763230306a5868447366474e3045636e76302b3561393557744a7942773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "polarity_flipped_with_its_mapping_with_only_the_circuit_leg_carried", + "note": "Only `active_high`, `mapping` change, together: a polarity flip whose mapping flips with it. The other leg is redone and the circuit leg is carried. A consumer that exempted the circuit leg for a polarity flip whose mapping flips with it accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "2 fields changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": true + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:f4ec773e931e51084b87538fecdf60fbd9c9a60ee24b9d0a455bc1e2344c7d64", + "signature_b64": "DrKo5RaC3iWtAB8Cxx/c9IFjxgufApX+yl8qcBbS9WfpaBLOpSJUUWjaFbnfIBakon/tPcHW3exwoz31GUt4Bw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a44724b6f35526143336957744142384378782f633949466a786775664170582b796c3871634262533957667061424c4f70534a5555576a6146626e664942616b6f6e2f7450634857336578776f7a33314755743442773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "every_field_changed_with_only_the_circuit_leg_carried", + "note": "The sensor and the actuator are both redeclared in every field. The other leg is redone and the circuit leg is carried. A consumer that exempted the circuit leg once enough fields changed, reading the zone as new rather than revised, accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "11 fields changed; the circuit leg carried", + "zones": [ + { + "zone_id": "main-distribution", + "rated_capacity": { + "parameter": "rated_capacity_amps", + "value": 10.0, + "provenance": "nameplate" + }, + "sensor": { + "sensor_id": "load-current-feeder", + "quantity": "current_rms", + "unit": "amp", + "range_min": 1.0, + "range_max": 150.0, + "direction": "negative_is_load_draw", + "noise_floor": 0.07, + "calibration_ref": "sct013-100-2026-09-01-d" + }, + "actuator": { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": true + }, + "commissioned_mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + } + }, + "proof": { + "method": "actuate_and_observe", + "performed_at_ms": 1800000000000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } + } + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main", + "load-current-feeder" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a223131206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:6c1b322a347ab4e9b67933776fa9b1284682146d3f26e8df24fc81c1d998d24d", + "signature_b64": "XLtOPgag5JVIu7JhpjtTtGEVJgIawLij2bSlTqYAEuuq44SBxTmW2WMNxobWrwqbRJO3orye1u+XZowHY4A3AQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a223131206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a584c744f50676167354a564975374a68706a7454744745564a674961774c696a3262536c54715941457575713434534278546d5732574d4e786f625772777162524a4f336f72796531752b585a6f77485934413341513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "sensor_replaced_with_only_the_control_leg_carried", + "note": "Only `sensor_id`, `calibration_ref` change, together: a replaced clamp. The other leg is redone and the control leg is carried. A consumer that exempted the control leg for a replaced clamp accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "2 fields changed; the control leg carried", + "zones": [ { - "zone_id": "borehole-pump", + "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 4.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-feeder", "quantity": "current", "unit": "ampere", "range_min": 0.0, "range_max": 100.0, "direction": "positive_is_load_draw", "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" + "calibration_ref": "sct013-100-2026-09-01-d" }, "actuator": { - "kind": "firmware_channel", + "kind": "local_gpio", "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "gpio_pin": 26, + "active_high": false }, "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "energised", + "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", - "coil_state": "de_energised", + "coil_state": "energised", + "gpio_level": "low", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-feeder" ], "actuators": [ { @@ -2718,41 +13607,59 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:1e11efd341282f5d705d7bd72f3e785e4dcc431e9a8665f4cb030dc4936d2347", - "signature_b64": "W0vWatMfpI4N9cU5udt9sDMF7rVNhwjdaTr6YWdwkEb18Qi6U+tyx4HGokeskaikvezCkR38Cyl/eqWXH4pPAg==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a5730765761744d667049344e396355357564743973444d463772564e68776a6461547236595764776b45623138516936552b7479783448476f6b65736b61696b76657a436b52333843796c2f657157584834705041673d3d227d", - "reason": "mapping_contradiction", - "stage": "mapping_self_consistency", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:5650dd1b7b08781486084b06fef1dea905d2f3e4cee2bd3389ebbb34ed7cac05", + "signature_b64": "f/0NRRahDO9s9kn7M54SCsTgc6HU/MZxtuWugIc5R8bBAvCmaA0W4Hj/wND8V+NjwepIVPrLsVP3KC2S6b1ODg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a662f304e52526168444f3973396b6e374d35345343735467633648552f4d5a787475577567496335523862424176436d6141305734486a2f774e4438562b4e6a776570495650724c735650334b4332533662314f44673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "terminal_state_contradicts_open_outcome", - "note": "`open_protected_circuit` is `de_energised` while `de_energised_terminal_state` is `closed`. Both cannot be observations of the same channel.", + "name": "actuator_replaced_with_only_the_control_leg_carried", + "note": "Only `gpio_pin`, `active_high` change, together: a replaced driver. The other leg is redone and the control leg is carried. A consumer that exempted the control leg for a replaced driver accepts it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "2 fields changed; the control leg carried", "zones": [ { "zone_id": "main-distribution", @@ -2774,23 +13681,23 @@ "actuator": { "kind": "local_gpio", "identity": { - "gpio_pin": 26, - "active_high": false + "gpio_pin": 19, + "active_high": true }, "commissioned_mapping": { "open_protected_circuit": "de_energised", "close_protected_circuit": "energised", - "de_energised_terminal_state": "closed" + "de_energised_terminal_state": "open" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", "coil_state": "de_energised", - "gpio_level": "high", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, "sensor_before": 6.4, @@ -2800,38 +13707,139 @@ { "commanded": "close_protected_circuit", "coil_state": "energised", - "gpio_level": "low", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, "sensor_before": 0.02, "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } - }, + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": true + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:6f9cff104e5dbec4257a1254e6a207ee8020a90108daf21dc2c7fd4f928bc772", + "signature_b64": "jh0tIBP4DG4ktiUFhy99D1TCPM3O+ebgup5m8AprDN9vZP7YiOT0NdSFOo65X7f+aN7hysC+CMI5dFcdzYFGDA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6a683074494250344447346b746955466879393944315443504d334f2b6562677570356d38417072444e39765a503759694f54304e6453464f6f36355837662b614e37687973432b434d4935644663647a59464744413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "rewired_to_another_pin_with_only_the_control_leg_carried", + "note": "Only `gpio_pin`, `mapping` change, together: a rewired actuator. The other leg is redone and the control leg is carried. A consumer that exempted the control leg for a rewired actuator accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "2 fields changed; the control leg carried", + "zones": [ { - "zone_id": "borehole-pump", + "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 4.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-main", "quantity": "current", "unit": "ampere", "range_min": 0.0, "range_max": 100.0, "direction": "positive_is_load_draw", "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" + "calibration_ref": "sct013-100-2026-08-19-a" }, "actuator": { - "kind": "firmware_channel", + "kind": "local_gpio", "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "gpio_pin": 19, + "active_high": false }, "commissioned_mapping": { "open_protected_circuit": "energised", @@ -2841,92 +13849,137 @@ }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", "coil_state": "energised", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { "kind": "local_gpio", "identity": { - "gpio_pin": 26, + "gpio_pin": 19, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:8d69fada11ea6d4310924051f2390e482f9179327c42fd064f4461402031e944", - "signature_b64": "T+MSMjiTnlvLNNAMdZlvN5eU3KHEfW8Nu0Ib/CmYokfbzoXW2MSv2DKQFmesJEQirekevksudfF1p4SeDzX2Ag==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a542b4d534d6a69546e6c764c4e4e414d645a6c764e356555334b48456657384e753049622f436d596f6b66627a6f5857324d537632444b51466d65734a45516972656b65766b73756466463170345365447a583241673d3d227d", - "reason": "mapping_contradiction", - "stage": "mapping_self_consistency", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:58129c263a9dd557793cff85df4e6b64886c0bd18fa6dd503fd344f994e11d1d", + "signature_b64": "uMKLsqxa69s2iBWUlIIvi5HUiZBVxvBW3Rq9jn7wa2Xr/H+uFigl4HlPtdbxbDzts0b2JHiH6wsIea1Lb3tYCw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a754d4b4c7371786136397332694257556c49497669354855695a425678764257335271396a6e3777613258722f482b754669676c34486c507464627862447a74733062324a486948367773496561314c6233745943773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "capacity_above_sensor_full_scale", - "note": "A 120 A capacity on a clamp that reads to 100 A describes a load the sensor cannot measure at all.", + "name": "polarity_flipped_with_its_mapping_with_only_the_control_leg_carried", + "note": "Only `active_high`, `mapping` change, together: a polarity flip whose mapping flips with it. The other leg is redone and the control leg is carried. A consumer that exempted the control leg for a polarity flip whose mapping flips with it accepts it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "2 fields changed; the control leg carried", "zones": [ { "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 120.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { @@ -2943,21 +13996,21 @@ "kind": "local_gpio", "identity": { "gpio_pin": 26, - "active_high": false + "active_high": true }, "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "de_energised", + "coil_state": "energised", "gpio_level": "high", "load_present_before": true, "load_present_after": false, @@ -2967,7 +14020,7 @@ }, { "commanded": "close_protected_circuit", - "coil_state": "energised", + "coil_state": "de_energised", "gpio_level": "low", "load_present_before": false, "load_present_after": true, @@ -2975,157 +14028,146 @@ "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, - "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "energised", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "de_energised", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, - "terminal_state_observed": "closed" - } - ] } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { "kind": "local_gpio", "identity": { "gpio_pin": 26, - "active_high": false - } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "active_high": true } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a3132302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:dfb6cddd460c1c1c053c569cc618649cbed271a921586df099f2d1dd0d7eb828", - "signature_b64": "kuKwi20WA0cVMaaFoiTx/LGu8lqsNffrx+cQjqMzoGdhXzE2CmxhvBQxTj5kj044UrwBpxzH4h1RSgcylAbgDw==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a3132302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a6b754b7769323057413063564d6161466f6954782f4c4775386c71734e666672782b63516a714d7a6f476468587a4532436d786876425178546a356b6a3034345572774270787a4834683152536763796c41626744773d3d227d", - "reason": "out_of_bounds", - "stage": "bounds", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:30a0c72ca9e82f22541fac5e39ba50a8330ed282669b21bd0cd58ebbb1087d95", + "signature_b64": "y19Ypi3j5lZeb3UfxtSnGcqz9pFJkSZ75ZBji4WGRmWTsSPUA14MHVNJFi2WDsGLA+dj6bPYNuds+qqspfTNCQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2232206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a793139597069336a356c5a65623355667874536e4763717a3970464a6b535a37355a426a69345747526d5754735350554131344d48564e4a466932574473474c412b646a366250594e7564732b7171737066544e43513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "trip_point_above_sensor_full_scale", - "note": "Capacity is comfortably in range at 25 A, and the release-owned multiplier of 5.0 puts the trip point at 125 A, beyond the clamp's 100 A full scale. A saturating sensor reports the hazard as a merely high reading, so the cutoff can never fire. This is the case a capacity-only bound misses.", + "name": "every_field_changed_with_only_the_control_leg_carried", + "note": "The sensor and the actuator are both redeclared in every field. The other leg is redone and the control leg is carried. A consumer that exempted the control leg once enough fields changed, reading the zone as new rather than revised, accepts it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "11 fields changed; the control leg carried", "zones": [ { "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 25.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-main", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-a" + "sensor_id": "load-current-feeder", + "quantity": "current_rms", + "unit": "amp", + "range_min": 1.0, + "range_max": 150.0, + "direction": "negative_is_load_draw", + "noise_floor": 0.07, + "calibration_ref": "sct013-100-2026-09-01-d" }, "actuator": { "kind": "local_gpio", "identity": { - "gpio_pin": 26, - "active_high": false + "gpio_pin": 19, + "active_high": true }, "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "de_energised", + "coil_state": "energised", "gpio_level": "high", "load_present_before": true, "load_present_after": false, @@ -3135,7 +14177,7 @@ }, { "commanded": "close_protected_circuit", - "coil_state": "energised", + "coil_state": "de_energised", "gpio_level": "low", "load_present_before": false, "load_present_after": true, @@ -3143,120 +14185,110 @@ "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, - "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "energised", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "de_energised", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, - "terminal_state_observed": "closed" - } - ] } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ "load-current-main", - "load-current-pump" + "load-current-feeder" ], "actuators": [ { "kind": "local_gpio", "identity": { - "gpio_pin": 26, + "gpio_pin": 19, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a32352e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:22a528df81b4a856feba6f20e4387084f7467e84e988371a5c97e6434eb9bb6b", - "signature_b64": "agCSooI2XElCeya6iZEfd5qpX/EJkRvXaiABaS7UCNC0dEML6oOqW8bA1MFVQ6hs7iMPK1oNAS+/ZMsuBtPSBA==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a32352e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a616743536f6f493258456c4365796136695a456664357170582f454a6b5276586169414261533755434e433064454d4c366f4f7157386241314d46565136687337694d504b316f4e41532b2f5a4d73754274505342413d3d227d", - "reason": "out_of_bounds", - "stage": "bounds", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a223131206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:fc0581b8e6385ec868a6b6aa9efa3b6b91c65c6e222093f4b064882a97ca880f", + "signature_b64": "Yx77TJ2EWVeQNTHRo4fbpPcrUYm1u4MzQAfO+yJ+4FlNjr2nnR8YYBnohqOhkwtVb2jicsgXOcO0DqPZ9vjjCA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a223131206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d666565646572222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a59783737544a3245575665514e5448526f3466627050637255596d3175344d7a5141664f2b794a2b34466c4e6a72326e6e52385959426e6f68714f686b77745662326a69637367584f634f304471505a39766a6a43413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "signed_by_provisioning_authority", - "note": "Genuinely signed by the provisioning authority, which is why the verdict is reachable at all: it is decided after the signature verifies, so a stranger cannot manufacture the event by naming that key over a forged signature. Refused because the commercial plane must not be able to move a trip point by raising a declared capacity.", + "name": "actuator_kind_changed_carrying_the_circuit_leg", + "note": "The pump zone moves from a firmware relay channel to a local pin, keeping its name, clamp and mapping, and carries its circuit leg. The retained zone had no control leg, so the circuit leg decides it alone. A consumer that compared identities only within one actuator kind, and so saw no change, accepts it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, - "signer_id": "product-provisioning-prod", - "signing_key": "ed25519:11l5O7wTooGagnx2rbb7qKSa7gB/SfLQmS2ZuCWtLEg=", + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "pump moved from the relay board to a local pin", "zones": [ { "zone_id": "main-distribution", @@ -3332,10 +14364,10 @@ "calibration_ref": "sct013-100-2026-08-19-b" }, "actuator": { - "kind": "firmware_channel", + "kind": "local_gpio", "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "gpio_pin": 19, + "active_high": false }, "commissioned_mapping": { "open_protected_circuit": "energised", @@ -3354,7 +14386,8 @@ "load_present_after": false, "sensor_before": 2.1, "sensor_after": 0.01, - "terminal_state_observed": "open" + "terminal_state_observed": "open", + "gpio_level": "low" }, { "commanded": "close_protected_circuit", @@ -3363,7 +14396,8 @@ "load_present_after": true, "sensor_before": 0.01, "sensor_after": 2.1, - "terminal_state_observed": "closed" + "terminal_state_observed": "closed", + "gpio_level": "high" } ] } @@ -3376,8 +14410,8 @@ "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", "declared_inventory": { "sensor_ids": [ "load-current-main", @@ -3391,40 +14425,86 @@ "active_high": false } }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } - } - ] - }, - "deployment_posture": "production", - "profile_multiplier": 5.0 + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000 + }, + "borehole-pump": { + "identity": { + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" + }, + "mapping": { + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" + }, + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "proof_at_ms": 1800000000000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a2270726f647563742d70726f766973696f6e696e672d70726f64222c227369676e696e675f6b6579223a22656432353531393a31316c354f3777546f6f4761676e783272626237714b53613767422f53664c516d53325a754357744c45673d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:86393af69774531b357ed8d0f2e37a12b91fc8310dda96e3a8848e99600f50a4", - "signature_b64": "b+nSeO1Ye0hw5Xaevo0deEqaotpuxEQnYoDIlEERmv8oy5yEqJ4gQi9wgloQou4cPC1hq82JkgYyOmvlmwMOCw==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a2270726f647563742d70726f766973696f6e696e672d70726f64222c227369676e696e675f6b6579223a22656432353531393a31316c354f3777546f6f4761676e783272626237714b53613767422f53664c516d53325a754357744c45673d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a622b6e53654f31596530687735586165766f3064654571616f7470757845516e596f44496c4545526d76386f79357945714a346751693977676c6f516f753463504331687138324a6b6759794f6d766c6d774d4f43773d3d227d", - "reason": "wrong_authority", - "stage": "authority", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70206d6f7665642066726f6d207468652072656c617920626f61726420746f2061206c6f63616c2070696e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", + "canonical_sha256": "sha256:0a0d2cc0dae5d32a5fc81c29815ab7475078493ea63563699544832ddecf0f40", + "signature_b64": "PEMucuRTttxR8ozXSUHCvX7k7Tb74x52r54i+zJg+0BbAI5hPjl6po+21UxuuCxvP+mcbvVAEMZwzfJyPMq5BQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70206d6f7665642066726f6d207468652072656c617920626f61726420746f2061206c6f63616c2070696e222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a50454d756375525474747852386f7a58535548437658376b3754623734783532723534692b7a4a672b30426241493568506a6c36706f2b323155787575437876502b6d6362765641454d5a777a664a79504d713542513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "signed_by_previous_commissioning_generation", - "note": "The previous generation is verify-only for the binding already in force. A new binding must be signed by the current generation, or a compromised key would keep authoring bindings after rotation.", + "name": "control_leg_carried_behind_a_fresh_pre_energisation_leg", + "note": "The clamp is recalibrated and the circuit leg redone as a pre_energisation meter proof, but the control leg is carried. A meter proof never drives the pin, so it cannot stand in for the control leg; a consumer that exempted the control leg behind one accepts it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", - "signing_key": "ed25519:xoImN8fTEOxXYnvgC6JZ0lN0n0qvZERwz/vlOjX3MkI=", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "clamp recalibrated; meter proof redone, control leg carried", "zones": [ { "zone_id": "main-distribution", @@ -3441,7 +14521,7 @@ "range_max": 100.0, "direction": "positive_is_load_draw", "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-a" + "calibration_ref": "sct013-100-2026-09-01-e" }, "actuator": { "kind": "local_gpio", @@ -3456,54 +14536,151 @@ } }, "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "method": "pre_energisation", + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", "coil_state": "de_energised", - "gpio_level": "high", "load_present_before": true, "load_present_after": false, - "sensor_before": 6.4, - "sensor_after": 0.02, - "terminal_state_observed": "open" + "terminal_state_observed": "open", + "instrument": "multimeter_continuity" }, { "commanded": "close_protected_circuit", "coil_state": "energised", - "gpio_level": "low", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.02, - "sensor_after": 6.4, - "terminal_state_observed": "closed" + "terminal_state_observed": "closed", + "instrument": "multimeter_continuity" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } - }, + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d7020726563616c696272617465643b206d657465722070726f6f66207265646f6e652c20636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a227072655f656e65726769736174696f6e222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d65222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:22818b7309a482bd1a3e9c807e344e09d016c9217ce725275a1e5081dad38219", + "signature_b64": "FkVToS856yfq/X4ACfV93/KcxNq0n/oxLAE4inrrNleBkhi43D7dsxjqwUTfTLlXBU6sAbKg9EcD6dkt4Do1BA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636c616d7020726563616c696272617465643b206d657465722070726f6f66207265646f6e652c20636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a227072655f656e65726769736174696f6e222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c22696e737472756d656e74223a226d756c74696d657465725f636f6e74696e75697479222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d65222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a466b56546f533835367966712f58344143665639332f4b63784e71306e2f6f784c414534696e72724e6c65426b6869343344376473786a7177555466544c6c584255367341624b673945634436646b7434446f3142413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "circuit_leg_carried_in_development_posture", + "note": "The mapping is rewired, the control leg redone and the circuit leg carried, in development posture. Posture decides what a provisional zone may do, not whether a carried proof is fresh; a consumer that held the circuit leg to its retained time only in production accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "contactor rewired; control leg redone, circuit leg carried", + "zones": [ { - "zone_id": "borehole-pump", + "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 4.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-main", "quantity": "current", "unit": "ampere", "range_min": 0.0, "range_max": 100.0, "direction": "positive_is_load_draw", "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" + "calibration_ref": "sct013-100-2026-08-19-a" }, "actuator": { - "kind": "firmware_channel", + "kind": "local_gpio", "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "gpio_pin": 26, + "active_high": false }, "commissioned_mapping": { "open_protected_circuit": "energised", @@ -3518,38 +14695,65 @@ { "commanded": "open_protected_circuit", "coil_state": "energised", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000900000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -3558,41 +14762,59 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, - "deployment_posture": "production", - "profile_multiplier": 5.0 + "deployment_posture": "development", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a786f496d4e386654454f7858596e766743364a5a306c4e306e3071765a4552777a2f766c4f6a58334d6b493d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:379bbe029c5d843180abe8cff5bb3d277767313e20af11261c23b484c534c588", - "signature_b64": "Ts6qjZlub1DUhlJfi4+QyWoNJWsnFYwvrtKubiH5fqiJ6bQoFEh9AQn7Ow1xbeUx4bUQJjp7OWPFIxh1escfDA==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a786f496d4e386654454f7858596e766743364a5a306c4e306e3071765a4552777a2f766c4f6a58334d6b493d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a547336716a5a6c7562314455686c4a6669342b5179576f4e4a57736e4659777672744b75626948356671694a3662516f4645683941516e374f77317862655578346255514a6a70374f575046497868316573636644413d3d227d", - "reason": "superseded_signer", - "stage": "authority", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636f6e74726f6c206c6567207265646f6e652c2063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:4d57c939f8ea157dec9a548bf2a165fc87b026d0bb785be6c1232733952f7073", + "signature_b64": "ss9hivVk3vKB7BSUjOuoI9CAZWJ7M8+AmNmdwJ+eeKoYGE6DXGycQClwAwMPTlskieGqH62hOpQEMYmDaIxJAQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22636f6e746163746f7220726577697265643b20636f6e74726f6c206c6567207265646f6e652c2063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a737339686976566b33764b42374253556a4f756f493943415a574a374d382b416d4e6d64774a2b65654b6f59474536445847796351436c7741774d50546c736b69654771483632684f7051454d596d446149784a41513d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "signing_key_is_not_a_commissioning_generation", - "note": "Self-consistent - the document names the key that signed it - and that key is neither generation of the commissioning anchor.", + "name": "circuit_leg_carried_in_staging_posture", + "note": "The mapping is rewired, the other leg redone and the circuit leg carried, in staging posture. Posture never decides whether a carried proof is fresh; a consumer that held the leg to its retained time only in production accepts it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", - "signing_key": "ed25519:My6+jSfLcyOzpAHBwTtd1kvMwOEOzaHCtdEaA3eaheU=", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "1 fields changed; the circuit leg carried", "zones": [ { "zone_id": "main-distribution", @@ -3617,62 +14839,6 @@ "gpio_pin": 26, "active_high": false }, - "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" - } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "de_energised", - "gpio_level": "high", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 6.4, - "sensor_after": 0.02, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "low", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.02, - "sensor_after": 6.4, - "terminal_state_observed": "closed" - } - ] - } - }, - { - "zone_id": "borehole-pump", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 4.0, - "provenance": "nameplate" - }, - "sensor": { - "sensor_id": "load-current-pump", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" - }, - "actuator": { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - }, "commissioned_mapping": { "open_protected_circuit": "energised", "close_protected_circuit": "de_energised", @@ -3686,38 +14852,65 @@ { "commanded": "open_protected_circuit", "coil_state": "energised", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800001200000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { @@ -3726,41 +14919,59 @@ "gpio_pin": 26, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, - "deployment_posture": "production", - "profile_multiplier": 5.0 + "deployment_posture": "staging", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a4d79362b6a53664c63794f7a7041484277547464316b764d774f454f7a61484374644561413365616865553d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:f6a83d2c125a1f5b16280b60dd2ade604309aa798cc8cd0e4b5ed94b7ef8b676", - "signature_b64": "9mADH9ETMzYN7iTASa/Yes9BIQWlJlYvcJFBeHLupZcw3EvMf5g0zJcLkdA1uQs4CxEo7ei4U3Oy34X3m9QkDA==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a4d79362b6a53664c63794f7a7041484277547464316b764d774f454f7a61484374644561413365616865553d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a396d4144483945544d7a594e3769544153612f59657339424951576c4a6c5976634a464265484c75705a63773345764d663567307a4a634c6b644131755173344378456f3765693455334f79333458336d39516b44413d3d227d", - "reason": "unknown_signer", - "stage": "key_selection", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2231206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:e77249b9dcd22c5d28dfe2f9dc79ac99095477494bdb134ad4381284276432df", + "signature_b64": "kwjNaM80xYwq5i89sXVUPMgBImOBi+3R+rn4EwNiU1OhhDHphJkIUyCibetqK6YOD7wMvYsP1D+F9q09/Y/ODw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2231206669656c6473206368616e6765643b207468652063697263756974206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030313230303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a6b776a4e614d3830785977713569383973585655504d6742496d4f42692b33522b726e3445774e6955314f6868444870684a6b4955794369626574714b36594f4437774d7659735031442b46397130392f592f4f44773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "anchors_are_identical_key_material", - "note": "Both configured anchors are the same 32 bytes, so `wrong_authority` could never be reached and the separation the contract rests on does not exist. Refused at configuration load, before any document is verified.", + "name": "control_leg_carried_in_staging_posture", + "note": "The mapping is rewired, the other leg redone and the control leg carried, in staging posture. Posture never decides whether a carried proof is fresh; a consumer that held the leg to its retained time only in production accepts it.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "1 fields changed; the control leg carried", "zones": [ { "zone_id": "main-distribution", @@ -3786,19 +14997,19 @@ "active_high": false }, "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" } }, "proof": { "method": "actuate_and_observe", - "performed_at_ms": 1800000000000, + "performed_at_ms": 1800000900000, "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "de_energised", - "gpio_level": "high", + "coil_state": "energised", + "gpio_level": "low", "load_present_before": true, "load_present_after": false, "sensor_before": 6.4, @@ -3807,44 +15018,145 @@ }, { "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "low", + "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": false, "load_present_after": true, "sensor_before": 0.02, "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } - }, + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 26, + "active_high": false + } + } + ] + }, + "deployment_posture": "staging", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2231206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:eb14be0216b532f9ccb2e884efcd399a262d5e9de42ef059f0347bc48d1c338f", + "signature_b64": "9Jwv7furIGdwyhsEuNwb3LdyX9TduGIjsUxDE+uy1vGpBYM1S9U0Q6EpqJa3YY1UE2EJ93NXAq8z3stqg0l4Bg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2231206669656c6473206368616e6765643b2074686520636f6e74726f6c206c65672063617272696564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a394a7776376675724947647779687345754e7762334c6479583954647547496a73557844452b75793176477042594d315339553051364570714a6133595931554532454a39334e584171387a3373747167306c3442673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "actuator_kind_changed_to_firmware_carrying_the_circuit_leg", + "note": "A zone in force on a local pin moves to a firmware relay channel, keeping its name, clamp and mapping, and carries its circuit leg; a firmware zone claims no control leg. A consumer that compared identities only within one actuator kind, and so saw no change, accepts it.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "main contactor moved from the local pin to a relay board", + "zones": [ { - "zone_id": "borehole-pump", + "zone_id": "main-distribution", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 4.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-main", "quantity": "current", "unit": "ampere", "range_min": 0.0, "range_max": 100.0, "direction": "positive_is_load_draw", "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" + "calibration_ref": "sct013-100-2026-08-19-a" }, "actuator": { "kind": "firmware_channel", "identity": { "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "channel": "relay1" }, "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" } }, "proof": { @@ -3853,20 +15165,20 @@ "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "energised", + "coil_state": "de_energised", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", - "coil_state": "de_energised", + "coil_state": "energised", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } ] @@ -3879,59 +15191,76 @@ "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", - "provisioning_anchor_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", - "accepted_binding_seq": 0, - "accepted_binding_hash": null, + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ - { - "kind": "local_gpio", - "identity": { - "gpio_pin": 26, - "active_high": false - } - }, { "kind": "firmware_channel", "identity": { "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "channel": "relay1" } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", - "signature_b64": "rIduw/4kEkG2P37R51vFXmNo/wYXQT/IorkRlkTLtFbt6zO44w6msHojREDx+UK18hQQ+hXmAbFTJpp3fTJHDg==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a72496475772f346b456b47325033375235317646586d4e6f2f77595851542f496f726b526c6b544c74466274367a4f343477366d73486f6a524544782b554b31386851512b68586d416246544a70703366544a4844673d3d227d", - "reason": "anchor_collision", - "stage": "key_selection", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e20636f6e746163746f72206d6f7665642066726f6d20746865206c6f63616c2070696e20746f20612072656c617920626f617264222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617931222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", + "canonical_sha256": "sha256:c64eb77bf7764412ce636071e3948419542f4a436c9430513773015363a6f191", + "signature_b64": "c6oeYnKofOc3orsNvuZGmwBCW9XiivBuXK4o0Zgnb11xGvHft/YCakyyce7lf3eSaXLJoY0t0TETknFaxXE/Aw==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a226d61696e20636f6e746163746f72206d6f7665642066726f6d20746865206c6f63616c2070696e20746f20612072656c617920626f617264222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617931222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a63366f65596e4b6f664f63336f72734e76755a476d7742435739586969764275584b346f305a676e6231317847764866742f5943616b79796365376c6633655361584c4a6f593074305445546b6e46617858452f41773d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "replayed_binding_seq", - "note": "`binding_seq` does not strictly exceed the accepted one.", + "name": "zone_found_by_its_sensor_id_alone", + "note": "The revision renames the zone, moves it to another pin and redeclares every sensor field but `sensor_id`, carrying both legs. Only the sensor_id finds the retained zone, so a consumer that matched a sensor by its id together with any other field finds nothing.", "binding": { "v": 1, - "binding_seq": 1, + "binding_seq": 2, "device_id": "energy-monitor-ikeja-01", "issued_at_ms": 1800000000000, "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": null, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "zone renamed; contactor moved to pin 19; clamp re-declared", "zones": [ { - "zone_id": "main-distribution", + "zone_id": "main-on-19", "rated_capacity": { "parameter": "rated_capacity_amps", "value": 10.0, @@ -3939,18 +15268,18 @@ }, "sensor": { "sensor_id": "load-current-main", - "quantity": "current", - "unit": "ampere", - "range_min": 0.0, - "range_max": 100.0, - "direction": "positive_is_load_draw", - "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-a" + "quantity": "current_rms", + "unit": "amp", + "range_min": 1.0, + "range_max": 150.0, + "direction": "negative_is_load_draw", + "noise_floor": 0.07, + "calibration_ref": "sct013-100-2026-09-01-d" }, "actuator": { "kind": "local_gpio", "identity": { - "gpio_pin": 26, + "gpio_pin": 19, "active_high": false }, "commissioned_mapping": { @@ -3983,36 +15312,137 @@ "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } - }, + } + ] + }, + "expected_state": "in_force", + "verifier_context": { + "device_id": "energy-monitor-ikeja-01", + "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", + "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", + "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", + "accepted_binding_seq": 1, + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "declared_inventory": { + "sensor_ids": [ + "load-current-main" + ], + "actuators": [ + { + "kind": "local_gpio", + "identity": { + "gpio_pin": 19, + "active_high": false + } + } + ] + }, + "deployment_posture": "production", + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } + }, + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d65643b20636f6e746163746f72206d6f76656420746f2070696e2031393b20636c616d702072652d6465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d6f6e2d3139227d5d7d", + "canonical_sha256": "sha256:23ad700d020ae05644d04728a96621cabfe733f9b94e4ff1a0f04f0a07a7dd74", + "signature_b64": "PF4APmMUHvaSHvBqfvfSes0gIDfTXJ6B1jxhaH792mR2IrQNvFwiKFMiaVAGnKOA8Vt77WR9YCOhpKEy9OgnAA==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d65643b20636f6e746163746f72206d6f76656420746f2070696e2031393b20636c616d702072652d6465636c61726564222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30392d30312d64222c22646972656374696f6e223a226e656761746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30372c227175616e74697479223a2263757272656e745f726d73222c2272616e67655f6d6178223a3135302e302c2272616e67655f6d696e223a312e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70227d2c227a6f6e655f6964223a226d61696e2d6f6e2d3139227d5d7d2c227369676e6174757265223a22656432353531393a50463441506d4d554876615348764271667666536573306749446654584a3642316a786861483739326d52324972514e764677694b464d69615641476e4b4f41385674373757523959434f68704b4579394f676e41413d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", + "signature_valid": true + }, + { + "name": "zone_renamed_keeping_only_its_sensor", + "note": "The revision renames the zone and moves it to another pin, keeping only the clamp, and carries both proof legs. Its name and its actuator match no retained zone; only its sensor does, so only a consumer that finds the retained zone by the sensor refuses it. The retained proof was taken on the old contactor.", + "binding": { + "v": 1, + "binding_seq": 2, + "device_id": "energy-monitor-ikeja-01", + "issued_at_ms": 1800000000000, + "signer_id": "commissioning-lagos-ikeja", + "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", + "inventory_generation": 7, + "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", + "actor": "installer:ade", + "reason": "zone renamed; contactor moved to pin 19", + "zones": [ { - "zone_id": "borehole-pump", + "zone_id": "main-on-19", "rated_capacity": { "parameter": "rated_capacity_amps", - "value": 4.0, + "value": 10.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-main", "quantity": "current", "unit": "ampere", "range_min": 0.0, "range_max": 100.0, "direction": "positive_is_load_draw", "noise_floor": 0.05, - "calibration_ref": "sct013-100-2026-08-19-b" + "calibration_ref": "sct013-100-2026-08-19-a" }, "actuator": { - "kind": "firmware_channel", + "kind": "local_gpio", "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" + "gpio_pin": 19, + "active_high": false }, "commissioned_mapping": { - "open_protected_circuit": "energised", - "close_protected_circuit": "de_energised", - "de_energised_terminal_state": "closed" + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" } }, "proof": { @@ -4021,71 +15451,116 @@ "observations": [ { "commanded": "open_protected_circuit", - "coil_state": "energised", + "coil_state": "de_energised", + "gpio_level": "high", "load_present_before": true, "load_present_after": false, - "sensor_before": 2.1, - "sensor_after": 0.01, + "sensor_before": 6.4, + "sensor_after": 0.02, "terminal_state_observed": "open" }, { "commanded": "close_protected_circuit", - "coil_state": "de_energised", + "coil_state": "energised", + "gpio_level": "low", "load_present_before": false, "load_present_after": true, - "sensor_before": 0.01, - "sensor_after": 2.1, + "sensor_before": 0.02, + "sensor_after": 6.4, "terminal_state_observed": "closed" } - ] + ], + "control_path": { + "method": "commanded_and_observed", + "performed_at_ms": 1800000600000, + "observations": [ + { + "commanded": "open_protected_circuit", + "coil_state": "de_energised", + "gpio_level": "high", + "load_present_before": true, + "load_present_after": false, + "sensor_before": 6.4, + "sensor_after": 0.02, + "terminal_state_observed": "open" + }, + { + "commanded": "close_protected_circuit", + "coil_state": "energised", + "gpio_level": "low", + "load_present_before": false, + "load_present_after": true, + "sensor_before": 0.02, + "sensor_after": 6.4, + "terminal_state_observed": "closed" + } + ] + } } } ] }, - "expected_state": "provisional", + "expected_state": "in_force", "verifier_context": { "device_id": "energy-monitor-ikeja-01", "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", "accepted_binding_seq": 1, - "accepted_binding_hash": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", + "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", "declared_inventory": { "sensor_ids": [ - "load-current-main", - "load-current-pump" + "load-current-main" ], "actuators": [ { "kind": "local_gpio", "identity": { - "gpio_pin": 26, + "gpio_pin": 19, "active_high": false } - }, - { - "kind": "firmware_channel", - "identity": { - "firmware_device_id": "ori-fw-7c9f2b3a", - "channel": "relay0" - } } ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" + }, + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, + "proof_at_ms": 1800000000000, + "control_proof_at_ms": 1800000600000 + } + } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", - "signature_b64": "rIduw/4kEkG2P37R51vFXmNo/wYXQT/IorkRlkTLtFbt6zO44w6msHojREDx+UK18hQQ+hXmAbFTJpp3fTJHDg==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a312c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a6e756c6c2c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a72496475772f346b456b47325033375235317646586d4e6f2f77595851542f496f726b526c6b544c74466274367a4f343477366d73486f6a524544782b554b31386851512b68586d416246544a70703366544a4844673d3d227d", - "reason": "stale", - "stage": "freshness", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d65643b20636f6e746163746f72206d6f76656420746f2070696e203139222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d6f6e2d3139227d5d7d", + "canonical_sha256": "sha256:ffd0b44ca20e3ba95d8b3b9ab07193916274fe79f2c9f6de1de707bdcc2ee486", + "signature_b64": "mzK027VM5GuhBlVM27nI8T8jWu7TLv5sa+WcLBaPWswM9XoVsTPSinvNOdgPuVG4DJegwqhf1xyGHDmfP5B6Cg==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a227a6f6e652072656e616d65643b20636f6e746163746f72206d6f76656420746f2070696e203139222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a31397d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d6f6e2d3139227d5d7d2c227369676e6174757265223a22656432353531393a6d7a4b303237564d35477568426c564d32376e493854386a577537544c763573612b57634c4261505773774d39586f5673545053696e764e4f64675075564734444a6567777168663178794748446d665035423643673d3d227d", + "reason": "stale_proof", + "stage": "proof_consistency", "signature_valid": true }, { - "name": "supersedes_does_not_match_accepted", - "note": "`binding_seq` advances but `supersedes` names a document that is not the one in force, so the chain does not connect.", + "name": "firmware_zone_renamed_keeping_only_its_channel", + "note": "The revision renames the firmware zone and binds it to a different clamp, keeping the same board and channel, and carries its proof. Only the actuator identity matches a retained zone, and a firmware actuator is identified by its board and its channel together, so the retained zone is found and the carried proof is refused.", "binding": { "v": 1, "binding_seq": 2, @@ -4094,9 +15569,9 @@ "signer_id": "commissioning-lagos-ikeja", "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", "inventory_generation": 7, - "supersedes": "sha256:0000000000000000000000000000000000000000000000000000000000000000", + "supersedes": "sha256:91b8097bb45d1d07c87526fc69338d737fb3d97a290f72911423b63be45acacd", "actor": "installer:ade", - "reason": "initial commissioning", + "reason": "pump zone renamed; clamp moved to the tank input", "zones": [ { "zone_id": "main-distribution", @@ -4155,14 +15630,14 @@ } }, { - "zone_id": "borehole-pump", + "zone_id": "tank-circuit", "rated_capacity": { "parameter": "rated_capacity_amps", "value": 4.0, "provenance": "nameplate" }, "sensor": { - "sensor_id": "load-current-pump", + "sensor_id": "load-current-tank", "quantity": "current", "unit": "ampere", "range_min": 0.0, @@ -4221,7 +15696,7 @@ "declared_inventory": { "sensor_ids": [ "load-current-main", - "load-current-pump" + "load-current-tank" ], "actuators": [ { @@ -4241,37 +15716,17 @@ ] }, "deployment_posture": "production", - "profile_multiplier": 5.0 - }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a30303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d", - "canonical_sha256": "sha256:d25b085197f3d03c876a6a0cff99c075a870fd399f14737787b997f5e017e288", - "signature_b64": "wjGVbHLwSfYd0Xvt+TApOfC7PPkxyq75HYIiceOAecgLB4C30q3dViBiRjny/AOVDF8CDWp4GFdTnqp0yRydAQ==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a22696e697469616c20636f6d6d697373696f6e696e67222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a30303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d70756d70222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a22626f7265686f6c652d70756d70227d5d7d2c227369676e6174757265223a22656432353531393a776a475662484c7753665964305876742b5441704f66433750506b78797137354859496963654f416563674c423443333071336456694269526a6e792f414f564446384344577034474664546e7170307952796441513d3d227d", - "reason": "stale", - "stage": "freshness", - "signature_valid": true - }, - { - "name": "polarity_revised_without_a_fresh_control_proof", - "note": "The revision inverts the driver stage and redoes the circuit leg, but carries the control proof performed against the old polarity. That proof recorded which level drove which coil state on the previous stage; under the new one it asserts the opposite. Accepting it would bring the zone into force with the polarity established by a measurement taken on the wiring it replaced -- the unproven-polarity actuation the control leg exists to close, reached through a revision rather than a first commissioning. The circuit leg is fresh, so the verdict is decided by the control leg alone.", - "binding": { - "v": 1, - "binding_seq": 2, - "device_id": "energy-monitor-ikeja-01", - "issued_at_ms": 1800000000000, - "signer_id": "commissioning-lagos-ikeja", - "signing_key": "ed25519:F8t5+ytBIPKx7GXkGY1uCLKOgT/rAeSkAIObheGAgM4=", - "inventory_generation": 7, - "supersedes": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", - "actor": "installer:ade", - "reason": "driver board replaced; the stage inverts", - "zones": [ - { - "zone_id": "main-distribution", - "rated_capacity": { - "parameter": "rated_capacity_amps", - "value": 10.0, - "provenance": "nameplate" + "profile_multiplier": 5.0, + "accepted_zone_state": { + "main-distribution": { + "identity": { + "gpio_pin": 26, + "active_high": false + }, + "mapping": { + "open_protected_circuit": "de_energised", + "close_protected_circuit": "energised", + "de_energised_terminal_state": "open" }, "sensor": { "sensor_id": "load-current-main", @@ -4283,118 +15738,36 @@ "noise_floor": 0.05, "calibration_ref": "sct013-100-2026-08-19-a" }, - "actuator": { - "kind": "local_gpio", - "identity": { - "gpio_pin": 26, - "active_high": true - }, - "commissioned_mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" - } - }, - "proof": { - "method": "actuate_and_observe", - "performed_at_ms": 1800000900000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "de_energised", - "gpio_level": "low", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 6.4, - "sensor_after": 0.02, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "high", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.02, - "sensor_after": 6.4, - "terminal_state_observed": "closed" - } - ], - "control_path": { - "method": "commanded_and_observed", - "performed_at_ms": 1800000600000, - "observations": [ - { - "commanded": "open_protected_circuit", - "coil_state": "de_energised", - "gpio_level": "low", - "load_present_before": true, - "load_present_after": false, - "sensor_before": 6.4, - "sensor_after": 0.02, - "terminal_state_observed": "open" - }, - { - "commanded": "close_protected_circuit", - "coil_state": "energised", - "gpio_level": "high", - "load_present_before": false, - "load_present_after": true, - "sensor_before": 0.02, - "sensor_after": 6.4, - "terminal_state_observed": "closed" - } - ] - } - } - } - ] - }, - "expected_state": "in_force", - "verifier_context": { - "device_id": "energy-monitor-ikeja-01", - "commissioning_anchor_current_hex": "17cb79fb2b4120f2b1ec65e4198d6e08b28e813feb01e4a400839b85e18080ce", - "commissioning_anchor_previous_hex": "c6822637c7d310ec57627be00ba259d253749f4aaf644470cffbe53a35f73242", - "provisioning_anchor_hex": "d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48", - "accepted_binding_seq": 1, - "accepted_binding_hash": "sha256:e6dad2c03053975835cd859fee1d36264accab4fe6cabe7ca4c7fa7362f738a7", - "declared_inventory": { - "sensor_ids": [ - "load-current-main" - ], - "actuators": [ - { - "kind": "local_gpio", - "identity": { - "gpio_pin": 26, - "active_high": false - } - } - ] - }, - "deployment_posture": "production", - "profile_multiplier": 5.0, - "accepted_zone_state": { - "main-distribution": { + "proof_at_ms": 1800000000000 + }, + "borehole-pump": { "identity": { - "gpio_pin": 26, - "active_high": false + "firmware_device_id": "ori-fw-7c9f2b3a", + "channel": "relay0" }, "mapping": { - "open_protected_circuit": "de_energised", - "close_protected_circuit": "energised", - "de_energised_terminal_state": "open" + "open_protected_circuit": "energised", + "close_protected_circuit": "de_energised", + "de_energised_terminal_state": "closed" }, - "calibration_ref": "sct013-100-2026-08-19-a", - "proof_at_ms": 1800000000000, - "control_proof_at_ms": 1800000600000 + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, + "proof_at_ms": 1800000000000 } } }, - "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2264726976657220626f617264207265706c616365643b2074686520737461676520696e7665727473222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d", - "canonical_sha256": "sha256:71ed5d0bee72221ee384cb1331fa6381d63c78df3649e49ac3d559f5fddd10bd", - "signature_b64": "PMdX660f7C0CAN6TvMbXNGlz9XMlnHkdpCjU7nBOK6e4EDCPYK6CyjnWX9wFj+kb8E6C3e4r+owEr+7t/0OPBQ==", - "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2264726976657220626f617264207265706c616365643b2074686520737461676520696e7665727473222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a65366461643263303330353339373538333563643835396665653164333632363461636361623466653663616265376361346337666137333632663733386137222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a747275652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b22636f6e74726f6c5f70617468223a7b226d6574686f64223a22636f6d6d616e6465645f616e645f6f62736572766564222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303630303030307d2c226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303930303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d5d7d2c227369676e6174757265223a22656432353531393a504d64583636306637433043414e3654764d62584e476c7a39584d6c6e486b6470436a55376e424f4b36653445444350594b3643796a6e57583977466a2b6b6238453643336534722b6f7745722b37742f304f5042513d3d227d", + "canonical_hex": "7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70207a6f6e652072656e616d65643b20636c616d70206d6f76656420746f207468652074616e6b20696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d74616e6b222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a2274616e6b2d63697263756974227d5d7d", + "canonical_sha256": "sha256:bff63903ff6df972ff8d30bf76884ff698aaeed8e75398a993d4cf8318e0addb", + "signature_b64": "nONslpavpjNj8pQ60Y+gmutj+15WGc11md4gNNhkgtb3coSlRf7S3kRJ7kqfDwRG4Q+KlArw3bmV/DbbtbroDQ==", + "message_hex": "7b2262696e64696e67223a7b226163746f72223a22696e7374616c6c65723a616465222c2262696e64696e675f736571223a322c226465766963655f6964223a22656e657267792d6d6f6e69746f722d696b656a612d3031222c22696e76656e746f72795f67656e65726174696f6e223a372c226973737565645f61745f6d73223a313830303030303030303030302c22726561736f6e223a2270756d70207a6f6e652072656e616d65643b20636c616d70206d6f76656420746f207468652074616e6b20696e707574222c227369676e65725f6964223a22636f6d6d697373696f6e696e672d6c61676f732d696b656a61222c227369676e696e675f6b6579223a22656432353531393a463874352b79744249504b783747586b47593175434c4b4f67542f724165536b41494f6268654741674d343d222c2273757065727365646573223a227368613235363a39316238303937626234356431643037633837353236666336393333386437333766623364393761323930663732393131343233623633626534356163616364222c2276223a312c227a6f6e6573223a5b7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a22656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a226f70656e222c226f70656e5f70726f7465637465645f63697263756974223a2264655f656e65726769736564227d2c226964656e74697479223a7b226163746976655f68696768223a66616c73652c226770696f5f70696e223a32367d2c226b696e64223a226c6f63616c5f6770696f227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a2268696768222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30322c2273656e736f725f6265666f7265223a362e342c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226770696f5f6c6576656c223a226c6f77222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a362e342c2273656e736f725f6265666f7265223a302e30322c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a31302e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d61222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d6d61696e222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a226d61696e2d646973747269627574696f6e227d2c7b226163747561746f72223a7b22636f6d6d697373696f6e65645f6d617070696e67223a7b22636c6f73655f70726f7465637465645f63697263756974223a2264655f656e65726769736564222c2264655f656e657267697365645f7465726d696e616c5f7374617465223a22636c6f736564222c226f70656e5f70726f7465637465645f63697263756974223a22656e65726769736564227d2c226964656e74697479223a7b226368616e6e656c223a2272656c617930222c226669726d776172655f6465766963655f6964223a226f72692d66772d3763396632623361227d2c226b696e64223a226669726d776172655f6368616e6e656c227d2c2270726f6f66223a7b226d6574686f64223a22616374756174655f616e645f6f627365727665222c226f62736572766174696f6e73223a5b7b22636f696c5f7374617465223a22656e65726769736564222c22636f6d6d616e646564223a226f70656e5f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a66616c73652c226c6f61645f70726573656e745f6265666f7265223a747275652c2273656e736f725f6166746572223a302e30312c2273656e736f725f6265666f7265223a322e312c227465726d696e616c5f73746174655f6f62736572766564223a226f70656e227d2c7b22636f696c5f7374617465223a2264655f656e65726769736564222c22636f6d6d616e646564223a22636c6f73655f70726f7465637465645f63697263756974222c226c6f61645f70726573656e745f6166746572223a747275652c226c6f61645f70726573656e745f6265666f7265223a66616c73652c2273656e736f725f6166746572223a322e312c2273656e736f725f6265666f7265223a302e30312c227465726d696e616c5f73746174655f6f62736572766564223a22636c6f736564227d5d2c22706572666f726d65645f61745f6d73223a313830303030303030303030307d2c2272617465645f6361706163697479223a7b22706172616d65746572223a2272617465645f63617061636974795f616d7073222c2270726f76656e616e6365223a226e616d65706c617465222c2276616c7565223a342e307d2c2273656e736f72223a7b2263616c6962726174696f6e5f726566223a227363743031332d3130302d323032362d30382d31392d62222c22646972656374696f6e223a22706f7369746976655f69735f6c6f61645f64726177222c226e6f6973655f666c6f6f72223a302e30352c227175616e74697479223a2263757272656e74222c2272616e67655f6d6178223a3130302e302c2272616e67655f6d696e223a302e302c2273656e736f725f6964223a226c6f61642d63757272656e742d74616e6b222c22756e6974223a22616d70657265227d2c227a6f6e655f6964223a2274616e6b2d63697263756974227d5d7d2c227369676e6174757265223a22656432353531393a6e4f4e736c706176706a4e6a3870513630592b676d75746a2b313557476331316d6434674e4e686b67746233636f536c52663753336b524a376b71664477524734512b4b6c41727733626d562f4462627462726f44513d3d227d", "reason": "stale_proof", "stage": "proof_consistency", "signature_valid": true @@ -4569,7 +15942,16 @@ "close_protected_circuit": "energised", "de_energised_terminal_state": "open" }, - "calibration_ref": "sct013-100-2026-08-19-a", + "sensor": { + "sensor_id": "load-current-main", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-a" + }, "proof_at_ms": 1800000000000 }, "borehole-pump": { @@ -4582,7 +15964,16 @@ "close_protected_circuit": "de_energised", "de_energised_terminal_state": "closed" }, - "calibration_ref": "sct013-100-2026-08-19-b", + "sensor": { + "sensor_id": "load-current-pump", + "quantity": "current", + "unit": "ampere", + "range_min": 0.0, + "range_max": 100.0, + "direction": "positive_is_load_draw", + "noise_floor": 0.05, + "calibration_ref": "sct013-100-2026-08-19-b" + }, "proof_at_ms": 1800000000000 } } diff --git a/internal/binding/testdata/vectors/commissioned_safety_binding/revision-misreadings-v1.json b/internal/binding/testdata/vectors/commissioned_safety_binding/revision-misreadings-v1.json new file mode 100644 index 0000000..738c833 --- /dev/null +++ b/internal/binding/testdata/vectors/commissioned_safety_binding/revision-misreadings-v1.json @@ -0,0 +1,585 @@ +{ + "v": 1, + "note": "The revision rule of commissioned-safety-binding/v1 as a table of switches, and the misreadings of it the corpus must refuse. `reference` is the rule; each misreading overrides some of its switches. Every revision vector is decided under the reference and under each misreading, and each misreading must decide some vector against its declared verdict. Exemptions keyed on a set of fields are enumerated only for `change_events`, the changes the contract names.", + "reference": { + "match_name": true, + "match_actuator": true, + "match_sensor": true, + "sensor_match": "sensor_id", + "gpio_match": "pin", + "firmware_match": "identity", + "change_identity": true, + "identity_compare": "whole", + "change_mapping": true, + "change_sensor": "whole", + "rename_is_change": false, + "visit": "all", + "circuit_unclaimed_exempt": true, + "circuit_skip_if_control_fresh": false, + "circuit_only_single_match": false, + "circuit_strict": false, + "control_requires_claim": true, + "control_on": "any_change", + "control_skip_if_circuit_unclaimed": false, + "control_missing": "fresh", + "control_strict": false, + "one_to_one": false, + "control_only_single_match": false, + "circuit_skip_if_control_unclaimed": false, + "control_absent_stale": false, + "single_retained_time": false, + "fresh_against_every_match_once_changed": false, + "proof_change_is_change": false, + "claimed_methods": "any_but_undemonstrated", + "circuit_retained_time": "own", + "exempt": [], + "exempt_sets": [], + "exempt_at_least": [], + "exempt_kind_change": [], + "exempt_control_behind_pre_energisation": false, + "exempt_postures": [], + "control_retained_time": "own" + }, + "change_events": { + "sensor is replaced": [ + "calibration_ref", + "sensor_id" + ], + "actuator is replaced": [ + "active_high", + "gpio_pin" + ], + "actuator is rewired to another pin": [ + "gpio_pin", + "mapping" + ], + "polarity flips with its mapping": [ + "active_high", + "mapping" + ] + }, + "misreadings": { + "GPIO matched by whole identity": { + "gpio_match": "whole" + }, + "a new proof time is a change": { + "proof_change_is_change": true + }, + "actuator clause dropped": { + "match_actuator": false + }, + "calibration change ignored": { + "change_sensor": "ignore:calibration_ref" + }, + "circuit checked only on a single match": { + "circuit_only_single_match": true + }, + "circuit leg equal to the retained time is fresh": { + "circuit_strict": true + }, + "circuit leg exempt in development posture": { + "exempt_postures": [ + [ + "circuit", + "development" + ] + ] + }, + "circuit leg exempt in staging posture": { + "exempt_postures": [ + [ + "circuit", + "staging" + ] + ] + }, + "circuit leg exempt on a kind change to GPIO": { + "exempt_kind_change": [ + "GPIO" + ] + }, + "circuit leg exempt on a kind change to firmware": { + "exempt_kind_change": [ + "firmware" + ] + }, + "circuit leg exempt when 2 or more fields changed": { + "exempt_at_least": [ + [ + "circuit", + 2 + ] + ] + }, + "circuit leg exempt when 3 or more fields changed": { + "exempt_at_least": [ + [ + "circuit", + 3 + ] + ] + }, + "circuit leg exempt when only active_high changed": { + "exempt": [ + [ + "circuit", + "active_high" + ] + ] + }, + "circuit leg exempt when only calibration_ref changed": { + "exempt": [ + [ + "circuit", + "calibration_ref" + ] + ] + }, + "circuit leg exempt when only channel changed": { + "exempt": [ + [ + "circuit", + "channel" + ] + ] + }, + "circuit leg exempt when only direction changed": { + "exempt": [ + [ + "circuit", + "direction" + ] + ] + }, + "circuit leg exempt when only firmware_device_id changed": { + "exempt": [ + [ + "circuit", + "firmware_device_id" + ] + ] + }, + "circuit leg exempt when only gpio_pin changed": { + "exempt": [ + [ + "circuit", + "gpio_pin" + ] + ] + }, + "circuit leg exempt when only mapping changed": { + "exempt": [ + [ + "circuit", + "mapping" + ] + ] + }, + "circuit leg exempt when only noise_floor changed": { + "exempt": [ + [ + "circuit", + "noise_floor" + ] + ] + }, + "circuit leg exempt when only quantity changed": { + "exempt": [ + [ + "circuit", + "quantity" + ] + ] + }, + "circuit leg exempt when only range_max changed": { + "exempt": [ + [ + "circuit", + "range_max" + ] + ] + }, + "circuit leg exempt when only range_min changed": { + "exempt": [ + [ + "circuit", + "range_min" + ] + ] + }, + "circuit leg exempt when only sensor_id changed": { + "exempt": [ + [ + "circuit", + "sensor_id" + ] + ] + }, + "circuit leg exempt when only unit changed": { + "exempt": [ + [ + "circuit", + "unit" + ] + ] + }, + "circuit leg exempt when the actuator is replaced": { + "exempt_sets": [ + [ + "circuit", + [ + "active_high", + "gpio_pin" + ] + ] + ] + }, + "circuit leg exempt when the actuator is rewired to another pin": { + "exempt_sets": [ + [ + "circuit", + [ + "gpio_pin", + "mapping" + ] + ] + ] + }, + "circuit leg exempt when the polarity flips with its mapping": { + "exempt_sets": [ + [ + "circuit", + [ + "active_high", + "mapping" + ] + ] + ] + }, + "circuit leg exempt when the sensor is replaced": { + "exempt_sets": [ + [ + "circuit", + [ + "calibration_ref", + "sensor_id" + ] + ] + ] + }, + "circuit leg held to the earlier retained time": { + "circuit_retained_time": "earlier" + }, + "circuit skipped behind a fresh control leg": { + "circuit_skip_if_control_fresh": true + }, + "circuit skipped behind an unclaimed control leg": { + "circuit_skip_if_control_unclaimed": true + }, + "control leg checked only on a single match": { + "control_only_single_match": true + }, + "control leg checked only on an actuator or mapping change": { + "control_on": "identity_or_mapping" + }, + "control leg checked only on an identity change": { + "control_on": "identity" + }, + "control leg equal to the retained time is fresh": { + "control_strict": true + }, + "control leg exempt behind a pre_energisation circuit leg": { + "exempt_control_behind_pre_energisation": true + }, + "control leg exempt in development posture": { + "exempt_postures": [ + [ + "control", + "development" + ] + ] + }, + "control leg exempt in staging posture": { + "exempt_postures": [ + [ + "control", + "staging" + ] + ] + }, + "control leg exempt when 2 or more fields changed": { + "exempt_at_least": [ + [ + "control", + 2 + ] + ] + }, + "control leg exempt when 3 or more fields changed": { + "exempt_at_least": [ + [ + "control", + 3 + ] + ] + }, + "control leg exempt when only active_high changed": { + "exempt": [ + [ + "control", + "active_high" + ] + ] + }, + "control leg exempt when only calibration_ref changed": { + "exempt": [ + [ + "control", + "calibration_ref" + ] + ] + }, + "control leg exempt when only direction changed": { + "exempt": [ + [ + "control", + "direction" + ] + ] + }, + "control leg exempt when only gpio_pin changed": { + "exempt": [ + [ + "control", + "gpio_pin" + ] + ] + }, + "control leg exempt when only mapping changed": { + "exempt": [ + [ + "control", + "mapping" + ] + ] + }, + "control leg exempt when only noise_floor changed": { + "exempt": [ + [ + "control", + "noise_floor" + ] + ] + }, + "control leg exempt when only quantity changed": { + "exempt": [ + [ + "control", + "quantity" + ] + ] + }, + "control leg exempt when only range_max changed": { + "exempt": [ + [ + "control", + "range_max" + ] + ] + }, + "control leg exempt when only range_min changed": { + "exempt": [ + [ + "control", + "range_min" + ] + ] + }, + "control leg exempt when only sensor_id changed": { + "exempt": [ + [ + "control", + "sensor_id" + ] + ] + }, + "control leg exempt when only unit changed": { + "exempt": [ + [ + "control", + "unit" + ] + ] + }, + "control leg exempt when the actuator is replaced": { + "exempt_sets": [ + [ + "control", + [ + "active_high", + "gpio_pin" + ] + ] + ] + }, + "control leg exempt when the actuator is rewired to another pin": { + "exempt_sets": [ + [ + "control", + [ + "gpio_pin", + "mapping" + ] + ] + ] + }, + "control leg exempt when the polarity flips with its mapping": { + "exempt_sets": [ + [ + "control", + [ + "active_high", + "mapping" + ] + ] + ] + }, + "control leg exempt when the sensor is replaced": { + "exempt_sets": [ + [ + "control", + [ + "calibration_ref", + "sensor_id" + ] + ] + ] + }, + "control leg held to the later retained time": { + "control_retained_time": "later" + }, + "control leg skipped when the circuit leg is unclaimed": { + "control_skip_if_circuit_unclaimed": true + }, + "direction change ignored": { + "change_sensor": "ignore:direction" + }, + "dropped control leg is stale": { + "control_absent_stale": true + }, + "each retained zone matched to one revision zone": { + "one_to_one": true + }, + "firmware matched by board only": { + "firmware_match": "board" + }, + "firmware matched by channel only": { + "firmware_match": "channel" + }, + "first match only": { + "visit": "first" + }, + "fresh against every match once any changed": { + "fresh_against_every_match_once_changed": true + }, + "identity change ignored": { + "change_identity": false + }, + "identity change ignores the board": { + "identity_compare": "ignore_board" + }, + "identity change ignores the channel": { + "identity_compare": "ignore_channel" + }, + "last match only": { + "visit": "last" + }, + "latest-proof match only": { + "visit": "latest_proof" + }, + "lower range change ignored": { + "change_sensor": "ignore:range_min" + }, + "mapping change ignored": { + "change_mapping": false + }, + "missing control time is stale": { + "control_missing": "stale" + }, + "missing control time is the circuit time": { + "control_missing": "circuit_time" + }, + "name clause dropped": { + "match_name": false + }, + "name only when no actuator matches": { + "visit": "name_if_no_actuator" + }, + "one retained time for both legs": { + "single_retained_time": true + }, + "pre_energisation leg treated as unclaimed": { + "claimed_methods": "actuate_and_observe" + }, + "quantity change ignored": { + "change_sensor": "ignore:quantity" + }, + "range change ignored": { + "change_sensor": "ignore:range" + }, + "rename is a change": { + "rename_is_change": true + }, + "sensor change by id and calibration": { + "change_sensor": "id_and_calibration" + }, + "sensor change by id only": { + "change_sensor": "sensor_id" + }, + "sensor clause dropped": { + "match_sensor": false + }, + "sensor match first": { + "visit": "sensor_first" + }, + "sensor matched as a whole": { + "sensor_match": "whole" + }, + "sensor matched by id and calibration_ref": { + "sensor_match": "id_and:calibration_ref" + }, + "sensor matched by id and direction": { + "sensor_match": "id_and:direction" + }, + "sensor matched by id and noise_floor": { + "sensor_match": "id_and:noise_floor" + }, + "sensor matched by id and quantity": { + "sensor_match": "id_and:quantity" + }, + "sensor matched by id and range_max": { + "sensor_match": "id_and:range_max" + }, + "sensor matched by id and range_min": { + "sensor_match": "id_and:range_min" + }, + "sensor matched by id and unit": { + "sensor_match": "id_and:unit" + }, + "stop after the first passing match": { + "visit": "stop_after_pass" + }, + "stop at the first unchanged match": { + "visit": "break_on_unchanged" + }, + "unclaimed circuit leg held to the retained time": { + "circuit_unclaimed_exempt": false + }, + "unclaimed control leg held to the retained time": { + "control_requires_claim": false + }, + "unit change ignored": { + "change_sensor": "ignore:unit" + } + } +} diff --git a/internal/binding/vendored_manifest_test.go b/internal/binding/vendored_manifest_test.go new file mode 100644 index 0000000..b3277e6 --- /dev/null +++ b/internal/binding/vendored_manifest_test.go @@ -0,0 +1,74 @@ +// Copyright 2026 Ori Nexus Systems LTD +// SPDX-License-Identifier: Apache-2.0 + +package binding_test + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "os" + "path/filepath" + "sort" + "testing" +) + +// TestVendoredVectorsAreThePublishedArtifactsAtThePinnedRevision holds the +// vendored directory to its manifest. This is a local-edit check only: upstream +// drift is the refresh script's job, because only it can see ori-specs. +func TestVendoredVectorsAreThePublishedArtifactsAtThePinnedRevision(t *testing.T) { + raw, err := os.ReadFile(filepath.Join(corpusDir, "MANIFEST.json")) + if err != nil { + t.Fatalf("read manifest: %v", err) + } + var manifest struct { + SourceRepository string `json:"source_repository"` + SourceCommit string `json:"source_commit"` + Files map[string]string `json:"files"` + } + if err := json.Unmarshal(raw, &manifest); err != nil { + t.Fatalf("decode manifest: %v", err) + } + if manifest.SourceRepository != "ori-platform/ori-specs" { + t.Errorf("the manifest names %q as its source, not ori-platform/ori-specs", manifest.SourceRepository) + } + if manifest.SourceCommit == "" { + t.Error("the manifest pins no source_commit") + } + paths, err := filepath.Glob(filepath.Join(corpusDir, "*.json")) + if err != nil { + t.Fatalf("list vendored files: %v", err) + } + var present []string + for _, path := range paths { + if name := filepath.Base(path); name != "MANIFEST.json" { + present = append(present, name) + if _, ok := manifest.Files[name]; !ok { + t.Errorf("%s is vendored but not in the manifest; re-vendor with "+ + "scripts/refresh-binding-vectors.sh rather than adding it here", name) + } + } + } + if len(present) == 0 { + t.Fatal("no vendored files: the manifest would hold nothing") + } + names := make([]string, 0, len(manifest.Files)) + for name := range manifest.Files { + names = append(names, name) + } + sort.Strings(names) + for _, name := range names { + body, err := os.ReadFile(filepath.Join(corpusDir, name)) + if err != nil { + t.Errorf("%s is in the manifest but cannot be read (%v); re-vendor with "+ + "scripts/refresh-binding-vectors.sh", name, err) + continue + } + sum := sha256.Sum256(body) + if got := hex.EncodeToString(sum[:]); got != manifest.Files[name] { + t.Errorf("the vendored %s has been edited locally (sha256 %s, manifest %s); "+ + "re-vendor with scripts/refresh-binding-vectors.sh rather than editing it here", + name, got, manifest.Files[name]) + } + } +} diff --git a/internal/binding/verifier_conformance_test.go b/internal/binding/verifier_conformance_test.go index f13b788..5a93155 100644 --- a/internal/binding/verifier_conformance_test.go +++ b/internal/binding/verifier_conformance_test.go @@ -105,10 +105,10 @@ type wireContext struct { } `json:"actuators"` } `json:"declared_inventory"` AcceptedZoneState map[string]struct { - Identity map[string]any `json:"identity"` - Mapping map[string]string `json:"mapping"` - CalibrationRef string `json:"calibration_ref"` - ProofAtMs int64 `json:"proof_at_ms"` + Identity map[string]any `json:"identity"` + Mapping map[string]string `json:"mapping"` + Sensor wireSensor `json:"sensor"` + ProofAtMs int64 `json:"proof_at_ms"` // Absent when the retained document carried no control leg. ControlProofAtMs *int64 `json:"control_proof_at_ms"` } `json:"accepted_zone_state"` @@ -117,6 +117,70 @@ type wireContext struct { ExpectedMapping map[string]string `json:"expected_mapping"` } +// wireSensor is a retained sensor object as the corpus spells it. +type wireSensor struct { + SensorID string `json:"sensor_id"` + Quantity string `json:"quantity"` + Unit string `json:"unit"` + RangeMin json.Number `json:"range_min"` + RangeMax json.Number `json:"range_max"` + Direction string `json:"direction"` + NoiseFloor json.Number `json:"noise_floor"` + CalibrationRef string `json:"calibration_ref"` +} + +func (w wireSensor) sensor(t testing.TB) binding.Sensor { + t.Helper() + number := func(n json.Number) float64 { + v, err := n.Float64() + if err != nil { + t.Fatalf("retained sensor number %q: %v", n, err) + } + return v + } + if w.SensorID == "" { + t.Fatal("a retained zone state carries no sensor") + } + return binding.Sensor{ + SensorID: w.SensorID, Quantity: w.Quantity, Unit: w.Unit, + RangeMin: number(w.RangeMin), RangeMax: number(w.RangeMax), + Direction: w.Direction, NoiseFloor: number(w.NoiseFloor), + CalibrationRef: w.CalibrationRef, + } +} + +// retainedOrder is each accepted_zone_state key's position as the corpus wrote +// it, which a map decode loses. +func retainedOrder(t testing.TB, raw json.RawMessage) map[string]int { + t.Helper() + var ctx struct { + AcceptedZoneState json.RawMessage `json:"accepted_zone_state"` + } + if err := json.Unmarshal(raw, &ctx); err != nil { + t.Fatalf("decode verifier_context: %v", err) + } + order := map[string]int{} + if len(ctx.AcceptedZoneState) == 0 || string(ctx.AcceptedZoneState) == "null" { + return order + } + dec := json.NewDecoder(bytes.NewReader(ctx.AcceptedZoneState)) + if _, err := dec.Token(); err != nil { + t.Fatalf("accepted_zone_state: %v", err) + } + for dec.More() { + key, err := dec.Token() + if err != nil { + t.Fatalf("accepted_zone_state key: %v", err) + } + order[key.(string)] = len(order) + var skip json.RawMessage + if err := dec.Decode(&skip); err != nil { + t.Fatalf("accepted_zone_state value: %v", err) + } + } + return order +} + func decodeContext(t testing.TB, raw json.RawMessage) wireContext { t.Helper() dec := json.NewDecoder(bytes.NewReader(raw)) @@ -184,11 +248,13 @@ func bindingContext(t testing.TB, raw json.RawMessage) binding.Context { } ctx.DeclaredActuators = append(ctx.DeclaredActuators, ref) } + order := retainedOrder(t, raw) for zoneID, was := range w.AcceptedZoneState { ctx.AcceptedZoneState[zoneID] = binding.ZoneState{ + Seq: order[zoneID], Identity: was.Identity, Mapping: mappingOf(was.Mapping), - CalibrationRef: was.CalibrationRef, + Sensor: was.Sensor.sensor(t), ProofAtMs: was.ProofAtMs, ControlProofAtMs: was.ControlProofAtMs, } @@ -777,34 +843,53 @@ func TestRetainedStateBuiltFromGoValuesMatchesTheWire(t *testing.T) { // that any spurious "changed" verdict surfaces as stale_proof. ctx.AcceptedZoneState = map[string]binding.ZoneState{ "borehole-pump": { - Identity: map[string]any{"firmware_device_id": "ori-fw-7c9f2b3a", "channel": "relay0"}, - Mapping: binding.Mapping{OpenProtectedCircuit: "energised", CloseProtectedCircuit: "de_energised", DeEnergisedTerminalState: "closed"}, - CalibrationRef: "sct013-100-2026-08-19-b", - ProofAtMs: 1800000000000, + Identity: map[string]any{"firmware_device_id": "ori-fw-7c9f2b3a", "channel": "relay0"}, + Mapping: binding.Mapping{OpenProtectedCircuit: "energised", CloseProtectedCircuit: "de_energised", DeEnergisedTerminalState: "closed"}, + Sensor: corpusSensor("load-current-pump", "sct013-100-2026-08-19-b"), + ProofAtMs: 1800000000000, }, "main-distribution": { - Identity: map[string]any{"gpio_pin": 26, "active_high": false}, - Mapping: binding.Mapping{OpenProtectedCircuit: "de_energised", CloseProtectedCircuit: "energised", DeEnergisedTerminalState: "open"}, - CalibrationRef: "sct013-100-2026-08-19-a", - ProofAtMs: 1800000000000, + Identity: map[string]any{"gpio_pin": 26, "active_high": false}, + Mapping: binding.Mapping{OpenProtectedCircuit: "de_energised", CloseProtectedCircuit: "energised", DeEnergisedTerminalState: "open"}, + Sensor: corpusSensor("load-current-main", "sct013-100-2026-08-19-a"), + ProofAtMs: 1800000000000, }, } env := envelopeBytes("binding", revision.Binding, revision.SignatureB64) if _, err := binding.VerifyEnvelope(env, ctx); err != nil { t.Fatalf("revision with fresh proof refused against Go-built retained state: %v", err) } + // A sensor that differs in any field but calibration must trip it too. + rebound := ctx.AcceptedZoneState["main-distribution"] + rebound.Sensor.RangeMax = 50 + rebound.ProofAtMs = 1800000600000 + ctx.AcceptedZoneState["main-distribution"] = rebound + _, err := binding.VerifyEnvelope(env, ctx) + if r := refusalOf(t, err); r.Stage != binding.StageProofConsistency || r.Reason != binding.ReasonStaleProof { + t.Fatalf("a re-described sensor refused at %s (%s); want proof_consistency (stale_proof)", r.Stage, r.Reason) + } + rebound.Sensor.RangeMax = 100 + rebound.ProofAtMs = 1800000000000 + ctx.AcceptedZoneState["main-distribution"] = rebound // And the same state with a pin that differs must trip the revision rule. changed := ctx.AcceptedZoneState["main-distribution"] changed.Identity = map[string]any{"gpio_pin": 27, "active_high": false} changed.ProofAtMs = 1800000600000 ctx.AcceptedZoneState["main-distribution"] = changed - _, err := binding.VerifyEnvelope(env, ctx) + _, err = binding.VerifyEnvelope(env, ctx) r := refusalOf(t, err) if r.Stage != binding.StageProofConsistency || r.Reason != binding.ReasonStaleProof { t.Fatalf("refused at %s (%s); want proof_consistency (stale_proof)", r.Stage, r.Reason) } } +func corpusSensor(id, calibration string) binding.Sensor { + return binding.Sensor{ + SensorID: id, Quantity: "current", Unit: "ampere", RangeMin: 0, RangeMax: 100, + Direction: "positive_is_load_draw", NoiseFloor: 0.05, CalibrationRef: calibration, + } +} + func ExampleVerifyEnvelope() { _, err := binding.VerifyEnvelope([]byte(`{"binding":{},"signature":"x"}`), binding.Context{}) fmt.Println(err) @@ -932,3 +1017,39 @@ func TestRawRejectCasesAreRefusedFromBytes(t *testing.T) { }) } } + +// TestAFirmwareZoneIsFollowedAcrossARename holds a firmware-channel zone to the +// retained zone with the same identity under another name: the rule matches +// hardware, not the name, for every actuator kind. +func TestAFirmwareZoneIsFollowedAcrossARename(t *testing.T) { + c := loadFullCorpus(t) + var revision *rejectCase + for i := range c.Cases { + if c.Cases[i].Name == "revision_with_fresh_proof_accepted" { + revision = &c.Cases[i] + } + } + if revision == nil { + t.Fatal("corpus no longer carries revision_with_fresh_proof_accepted") + } + ctx := bindingContext(t, revision.VerifierContext) + env := envelopeBytes("binding", revision.Binding, revision.SignatureB64) + pump, ok := ctx.AcceptedZoneState["borehole-pump"] + if !ok { + t.Fatal("the case retains no borehole-pump zone") + } + delete(ctx.AcceptedZoneState, "borehole-pump") + pump.Mapping = binding.Mapping{ + OpenProtectedCircuit: "de_energised", CloseProtectedCircuit: "energised", + DeEnergisedTerminalState: "open", + } + // Another sensor too, so the firmware identity is the only thing shared. + pump.Sensor.SensorID = "clamp-before-rename" + pump.ProofAtMs = 1900000000000 + ctx.AcceptedZoneState["pump-before-rename"] = pump + _, err := binding.VerifyEnvelope(env, ctx) + r := refusalOf(t, err) + if r.Stage != binding.StageProofConsistency || r.Reason != binding.ReasonStaleProof { + t.Fatalf("a firmware zone under a new name kept its proof: %s (%s)", r.Stage, r.Reason) + } +} diff --git a/internal/binding/verify.go b/internal/binding/verify.go index 063ea3e..f50b95a 100644 --- a/internal/binding/verify.go +++ b/internal/binding/verify.go @@ -26,6 +26,7 @@ import ( "io" "math" "regexp" + "sort" "strconv" "strings" @@ -125,10 +126,13 @@ func (a ActuatorRef) key() string { type ZoneState struct { // Identity is the full identity object, active_high included, as the // accepted document carried it. - Identity map[string]any - Mapping Mapping - CalibrationRef string - ProofAtMs int64 + Identity map[string]any + Mapping Mapping + // Sensor is the whole sensor object, calibration_ref included: a proof + // records that this sensor observes this circuit, so a revision changing + // any of it asserts an association the retained proof never observed. + Sensor Sensor + ProofAtMs int64 // ControlProofAtMs is nil when the retained document carried no control // leg, in which case a revision's control leg is fresh by construction: // there is nothing it could be inheriting. A caller reconstructing this @@ -136,6 +140,9 @@ type ZoneState struct { // "no leg was ever proven" and lets a revision reuse a stale control // proof. ControlProofAtMs *int64 + // Seq is the zone's position in the retained document. The revision rule + // visits retained zones in that order, and in name order among equal Seq. + Seq int } // The control leg's own method vocabulary. `commanded_and_observed` establishes @@ -187,6 +194,7 @@ type AcceptedZone struct { Identity map[string]any Mapping Mapping CalibrationRef string + Sensor Sensor ProofMethod string ProofPerformedAtMs int64 // ControlProofMethod is "" when the leg is absent. Absence denies; a @@ -492,6 +500,7 @@ type parsedZone struct { rangeMax float64 noiseFloor float64 calibrationRef string + sensor Sensor kind string identity map[string]any ref ActuatorRef @@ -581,6 +590,12 @@ func parseZone(v any) (parsedZone, bool) { if !(z.rangeMin < z.rangeMax) || z.noiseFloor <= 0 { return z, false } + z.sensor = Sensor{ + SensorID: z.sensorID, Quantity: sensor["quantity"].(string), + Unit: sensor["unit"].(string), RangeMin: z.rangeMin, RangeMax: z.rangeMax, + Direction: sensor["direction"].(string), NoiseFloor: z.noiseFloor, + CalibrationRef: z.calibrationRef, + } actuator, ok := closed(obj["actuator"], actuatorKeys) if !ok { @@ -933,6 +948,15 @@ func (m Mapping) coilFor(outcome string) string { } func stProofConsistency(b *parsedBinding, prior map[string]ZoneState) *Refusal { + if r := stObservations(b); r != nil { + return r + } + return stRevisionRule(b, prior) +} + +// stObservations holds each claimed leg's observations to the mapping they +// claim to establish. +func stObservations(b *parsedBinding) *Refusal { for _, z := range b.zones { if z.method != MethodUnproven { if bad := checkObservations(z, z.observations); bad != nil { @@ -947,32 +971,73 @@ func stProofConsistency(b *parsedBinding, prior map[string]ZoneState) *Refusal { } } } - // A revision changing actuator identity, mapping or calibration needs a - // proof performed after the accepted document, leg by leg. - for _, z := range b.zones { - was, retained := prior[z.zoneID] - if !retained { - continue - } - changed := !sameIdentity(was.Identity, z.identity) || - was.Mapping != z.mapping || - was.CalibrationRef != z.calibrationRef - if !changed { - continue - } - if z.performedAtMs <= was.ProofAtMs { - return refuse(StageProofConsistency, ReasonStaleProof) + return nil +} + +// stRevisionRule is the revision rule: a changed zone cannot inherit the proof +// of the hardware it replaced. +func stRevisionRule(b *parsedBinding, prior map[string]ZoneState) *Refusal { + // A revision changing anything in a zone but its rated capacity -- the + // sensor, the actuator identity or the mapping -- needs a proof performed + // after the accepted document, leg by leg. + // + // A zone is held to every retained zone it shares a name, an actuator or a + // sensor with. Matched on the name alone, a renamed zone would carry its + // proof onto wiring nobody proved, and two zones exchanging sensors would + // each carry a proof onto the other circuit. + retainedIDs := make([]string, 0, len(prior)) + for zoneID := range prior { + retainedIDs = append(retainedIDs, zoneID) + } + sort.Slice(retainedIDs, func(i, j int) bool { + a, b := prior[retainedIDs[i]], prior[retainedIDs[j]] + if a.Seq != b.Seq { + return a.Seq < b.Seq } - // A changed pin or polarity invalidates the control proof too: it was - // performed on the wiring this revision replaces. - if z.controlMethod == ControlCommanded && was.ControlProofAtMs != nil && - z.controlPerformedAtMs <= *was.ControlProofAtMs { - return refuse(StageProofConsistency, ReasonStaleProof) + return retainedIDs[i] < retainedIDs[j] + }) + for _, z := range b.zones { + for _, zoneID := range retainedIDs { + was := prior[zoneID] + if zoneID != z.zoneID && !sameActuator(was.Identity, z.identity) && + was.Sensor.SensorID != z.sensor.SensorID { + continue + } + changed := !sameIdentity(was.Identity, z.identity) || + was.Mapping != z.mapping || + was.Sensor != z.sensor + if !changed { + continue + } + // Freshness applies to a leg the revision claims: an undemonstrated + // leg carries no proof, so it inherits nothing and leaves the zone + // provisional rather than stale. + if z.method != MethodUnproven && z.performedAtMs <= was.ProofAtMs { + return refuse(StageProofConsistency, ReasonStaleProof) + } + // A changed pin or polarity invalidates the control proof too: it + // was performed on the wiring this revision replaces. + if z.controlMethod == ControlCommanded && was.ControlProofAtMs != nil && + z.controlPerformedAtMs <= *was.ControlProofAtMs { + return refuse(StageProofConsistency, ReasonStaleProof) + } } } return nil } +// sameActuator compares two identities as the inventory does: a GPIO line by +// its pin, whatever polarity either records; anything else by the whole +// identity. +func sameActuator(retained, identity map[string]any) bool { + pinA, okA := retained["gpio_pin"] + pinB, okB := identity["gpio_pin"] + if okA && okB { + return sameIdentity(map[string]any{"gpio_pin": pinA}, map[string]any{"gpio_pin": pinB}) + } + return sameIdentity(retained, identity) +} + // checkObservations holds a set of observations to the mapping they claim to // establish, whichever leg carried them. func checkObservations(z parsedZone, observations []parsedObservation) *Refusal { @@ -1152,6 +1217,7 @@ func (b *parsedBinding) accepted(signature string) *Accepted { Identity: z.identity, Mapping: z.mapping, CalibrationRef: z.calibrationRef, + Sensor: z.sensor, ProofMethod: z.method, ProofPerformedAtMs: z.performedAtMs, ControlProofMethod: z.controlMethod, @@ -1171,6 +1237,14 @@ func (b *parsedBinding) accepted(signature string) *Accepted { // VerifyEnvelope verifies a binding envelope's wire bytes through the // contract's twelve stages in order. A non-nil error is always a *Refusal. func VerifyEnvelope(raw []byte, ctx Context) (*Accepted, error) { + return verifyEnvelope(raw, ctx, stProofConsistency) +} + +// verifyEnvelope takes the proof_consistency stage as a parameter so a test +// can hold the corpus to readings of the revision rule other than this one. +func verifyEnvelope( + raw []byte, ctx Context, proofStage func(*parsedBinding, map[string]ZoneState) *Refusal, +) (*Accepted, error) { body, sig, sigText, r := parseEnvelope(raw, "binding") if r != nil { return nil, r @@ -1202,7 +1276,7 @@ func VerifyEnvelope(raw []byte, ctx Context) (*Accepted, error) { if r := stMappingSelfConsistency(b); r != nil { return nil, r } - if r := stProofConsistency(b, ctx.AcceptedZoneState); r != nil { + if r := proofStage(b, ctx.AcceptedZoneState); r != nil { return nil, r } if r := stBounds(b, ctx.ProfileMultiplier); r != nil { diff --git a/internal/capture/capture.go b/internal/capture/capture.go index c0ade82..12a177f 100644 --- a/internal/capture/capture.go +++ b/internal/capture/capture.go @@ -28,6 +28,8 @@ type Asker interface { // Choose returns one of options. It must not accept anything else. Choose(prompt string, options []string) (string, error) Ask(prompt string) (string, error) + // Say tells the installer something that needs no answer. + Say(text string) } // Inventory is the runtime's declared hardware, as `commissioning inventory` @@ -156,7 +158,7 @@ func Capture(a Asker, inv Inventory, zoneID string, nowMs int64) (binding.Bindin return binding.Binding{}, err } - proof, err := captureProof(a, mapping, nowMs) + proof, err := captureProof(a, mapping, nowMs, 0) if err != nil { return binding.Binding{}, err } @@ -309,19 +311,30 @@ func captureMapping(a Asker) (binding.Mapping, error) { }, nil } +// maxProofSkewMs is how far past this machine's clock a proof may be dated +// before the time is refused as a typo: the next revision must follow it, and +// a proof dated centuries ahead would block every one. +const maxProofSkewMs = 5 * 60 * 1000 + // captureProof records how the mapping was established, or that it was not. // +// A revision passes the time of the proof in force as after, and a claimed leg +// time is refused as soon as it is given if it is not later: a leg no later +// than the one it replaces could be the proof of what the revision changed. +// // `commanded_and_observed` is absent by design: the control leg is proven by // the runtime commanding the coil, and its observations are read back from the // runtime rather than typed here. A leg this tool authored would record what // the tool asserted. -func captureProof(a Asker, mapping binding.Mapping, nowMs int64) (binding.Proof, error) { +func captureProof(a Asker, mapping binding.Mapping, nowMs, after int64) (binding.Proof, error) { method, err := a.Choose( "How was the circuit leg established?", []string{binding.MethodPreEnergy, binding.MethodUnproven}) if err != nil { return binding.Proof{}, err } + // An undemonstrated leg claims no proof, so it is not held to the time of + // the proof in force: it inherits nothing and leaves the zone provisional. if method == binding.MethodUnproven { reason, askErr := a.Ask("Why could no proof be performed?") if askErr != nil { @@ -341,6 +354,12 @@ func captureProof(a Asker, mapping binding.Mapping, nowMs int64) (binding.Proof, }, nil } + // A claimed leg must follow the proof in force and cannot be dated past + // this machine's clock; a proof in force dated beyond it leaves no time + // the leg could have, which is said before the time is asked for. + if after >= nowMs+maxProofSkewMs { + return binding.Proof{}, futureProofInForce(after, nowMs) + } performedAt, err := askInt(a, "When was that proof performed? Unix milliseconds:") if err != nil { @@ -350,6 +369,15 @@ func captureProof(a Asker, mapping binding.Mapping, nowMs int64) (binding.Proof, return binding.Proof{}, fmt.Errorf( "a proof records when it was performed; %d is not a time", performedAt) } + if performedAt > nowMs+maxProofSkewMs { + return binding.Proof{}, fmt.Errorf( + "a proof performed at %d is later than this machine's clock (%d); a "+ + "proof dated in the future would have to be followed by every later "+ + "revision", performedAt, nowMs) + } + if performedAt <= after { + return binding.Proof{}, notAfter(performedAt, after, nowMs) + } // A proof admits a non-empty observations list, and both outcomes must be // observed: one-sided proof establishes one direction, and the direction it @@ -563,3 +591,24 @@ func supersedes(inv Inventory) *string { hash := inv.AcceptedBindingHash return &hash } + +func notAfter(at, after, nowMs int64) error { + if after >= nowMs { + return futureProofInForce(after, nowMs) + } + return fmt.Errorf( + "a circuit leg performed at %d is not after the proof in force at %d, so "+ + "it could be the proof of what this revision replaced; it needs a proof "+ + "performed after the change", at, after) +} + +// futureProofInForce names why no fresh leg is possible: the proof in force is +// dated after this machine's clock, and a fresh leg has to follow it. +func futureProofInForce(after, nowMs int64) error { + return fmt.Errorf( + "the proof in force is dated %d, after this machine's clock (%d), and a "+ + "claimed leg has to be performed after it; no leg recorded now can be. "+ + "Record the leg undemonstrated, which is held to no time, or capture "+ + "this revision once the clock passes that time or the proof in force "+ + "is corrected", after, nowMs) +} diff --git a/internal/capture/capture_test.go b/internal/capture/capture_test.go index fcf7f83..bd4f411 100644 --- a/internal/capture/capture_test.go +++ b/internal/capture/capture_test.go @@ -16,6 +16,7 @@ type scripted struct { answers []string offered [][]string prompts []string + said []string at int } @@ -45,6 +46,8 @@ func (s *scripted) Choose(prompt string, options []string) (string, error) { func (s *scripted) Ask(prompt string) (string, error) { return s.next(prompt) } +func (s *scripted) Say(text string) { s.said = append(s.said, text) } + var ( errExhausted = errStr("the ceremony asked more questions than the script answers") errNotOffered = errStr("an answer outside the offered set was accepted") diff --git a/internal/capture/draft.go b/internal/capture/draft.go index e82f470..707ab86 100644 --- a/internal/capture/draft.go +++ b/internal/capture/draft.go @@ -25,6 +25,10 @@ func DraftJSON(b binding.Binding) ([]byte, error) { zones := make([]map[string]any, 0, len(b.Zones)) for _, z := range b.Zones { identity := map[string]any{} + if z.Actuator.Kind == binding.KindFirmware { + identity["firmware_device_id"] = z.Actuator.Identity.FirmwareDeviceID + identity["channel"] = z.Actuator.Identity.Channel + } if z.Actuator.Identity.GPIOPin != nil { identity["gpio_pin"] = *z.Actuator.Identity.GPIOPin } @@ -39,17 +43,20 @@ func DraftJSON(b binding.Binding) ([]byte, error) { // carries the time the determination was made and an empty list, and // a draft that omitted them would have signing invent both. proof["performed_at_ms"] = z.Proof.PerformedAtMs - observations := make([]map[string]any, 0, len(z.Proof.Observations)) - for _, o := range z.Proof.Observations { - observations = append(observations, map[string]any{ - "commanded": o.Commanded, - "coil_state": o.CoilState, - "terminal_state_observed": o.TerminalStateObserved, - "load_present_before": o.LoadPresentBefore, - "load_present_after": o.LoadPresentAfter, - }) + proof["observations"] = observationsJSON(z.Proof.Observations) + // A revision carries the control leg in force when nothing it changes + // invalidates it, and carries it exactly as it was signed. + if leg := z.Proof.ControlPath; leg != nil { + control := map[string]any{ + "method": leg.Method, + "performed_at_ms": leg.PerformedAtMs, + "observations": observationsJSON(leg.Observations), + } + if leg.Reason != "" { + control["reason"] = leg.Reason + } + proof["control_path"] = control } - proof["observations"] = observations zones = append(zones, map[string]any{ "zone_id": z.ZoneID, "rated_capacity": map[string]any{ @@ -86,9 +93,39 @@ func DraftJSON(b binding.Binding) ([]byte, error) { "inventory_generation": b.InventoryGeneration, "zones": zones, } + // A revision's reason is capture's: it carries the prior value of what + // changed. A first binding leaves it to signing. + if b.Reason != "" { + body["reason"] = b.Reason + } // Absent on a first binding, and absence is what says so. if b.Supersedes != nil { body["supersedes"] = *b.Supersedes } return json.MarshalIndent(body, "", " ") } + +func observationsJSON(observations []binding.Observation) []map[string]any { + out := make([]map[string]any, 0, len(observations)) + for _, o := range observations { + entry := map[string]any{ + "commanded": o.Commanded, + "coil_state": o.CoilState, + "terminal_state_observed": o.TerminalStateObserved, + "load_present_before": o.LoadPresentBefore, + "load_present_after": o.LoadPresentAfter, + } + if o.GPIOLevel != "" { + entry["gpio_level"] = o.GPIOLevel + } + if o.Instrument != "" { + entry["instrument"] = o.Instrument + } + if o.SensorBefore != nil && o.SensorAfter != nil { + entry["sensor_before"] = *o.SensorBefore + entry["sensor_after"] = *o.SensorAfter + } + out = append(out, entry) + } + return out +} diff --git a/internal/capture/revise.go b/internal/capture/revise.go new file mode 100644 index 0000000..6299470 --- /dev/null +++ b/internal/capture/revise.go @@ -0,0 +1,645 @@ +// Copyright 2026 Ori Nexus Systems LTD +// SPDX-License-Identifier: Apache-2.0 + +package capture + +import ( + "encoding/json" + "fmt" + "sort" + "strconv" + "strings" + "unicode/utf8" + + "github.com/ori-platform/ori-cli/internal/binding" +) + +// Proof states a revised zone can be left in. They are three different things +// and never reported as one another. +const ( + StateProven = "proven" + StateProvisional = "provisional" + StateUndemonstrated = "undemonstrated" +) + +const ( + answerUnchanged = "unchanged" + answerChanged = "changed" +) + +// Prior is the binding in force a revision is captured against: the document +// itself, and what a consumer retained from it. +type Prior struct { + Document binding.Binding + Accepted *binding.Accepted +} + +// Change is one fact a revision altered, with the value it replaced. +type Change struct { + Fact string `json:"fact"` + Was string `json:"was"` + Now string `json:"now"` +} + +// Revision is what a revision changed, what it carried, and the proof it needs. +type Revision struct { + Supersedes string `json:"supersedes"` + SupersedesSeq int64 `json:"supersedes_binding_seq"` + BindingSeq int64 `json:"binding_seq"` + ZoneID string `json:"zone_id"` + Changed []Change `json:"changed"` + Carried []string `json:"carried"` + CarriedZones []string `json:"carried_zones"` + FreshProof bool `json:"fresh_proof_required"` + Because []string `json:"fresh_proof_because"` + CircuitLegAfterMs int64 `json:"circuit_leg_after_ms"` + ControlLegAfterMs *int64 `json:"control_leg_after_ms"` + CircuitLeg string `json:"circuit_leg"` + ControlLeg string `json:"control_leg"` + ProofState string `json:"proof_state"` + TripPointBound string `json:"trip_point_bound"` + Reason string `json:"reason"` +} + +// LoadPrior binds a signed envelope to the binding the runtime reports in +// force. The runtime reports only the hash, so the document is what an +// installer presents, and it is trusted for nothing until its canonical hash +// is the one the runtime returned. +func LoadPrior(inv Inventory, envelope []byte) (Prior, error) { + if inv.AcceptedBindingHash == "" { + return Prior{}, fmt.Errorf( + "device %q reports no binding in force, so there is nothing to revise; "+ + "capture a first binding without --revise", inv.DeviceID) + } + accepted, err := binding.VerifyOffline(envelope) + if err != nil { + return Prior{}, fmt.Errorf( + "the document given as the binding in force does not verify (%v), so "+ + "nothing in it can be carried", err) + } + if accepted.CanonicalHash != inv.AcceptedBindingHash { + return Prior{}, fmt.Errorf( + "the document given hashes to %s, and the binding in force on device %q "+ + "is %s; a revision is captured against the binding in force and no other", + accepted.CanonicalHash, inv.DeviceID, inv.AcceptedBindingHash) + } + if accepted.BindingSeq != inv.AcceptedBindingSeq || accepted.DeviceID != inv.DeviceID { + return Prior{}, fmt.Errorf( + "the runtime reports binding %d on device %q with that hash, and the "+ + "document is binding %d for %q; the inventory does not describe it", + inv.AcceptedBindingSeq, inv.DeviceID, accepted.BindingSeq, accepted.DeviceID) + } + var env struct { + Binding json.RawMessage `json:"binding"` + } + if err := json.Unmarshal(envelope, &env); err != nil { + return Prior{}, fmt.Errorf("the binding in force is not readable: %w", err) + } + doc, _, err := binding.DecodeDocument(env.Binding) + if err != nil { + return Prior{}, fmt.Errorf("the binding in force is not readable: %w", err) + } + return Prior{Document: doc, Accepted: accepted}, nil +} + +// Exported is what `commissioning binding-export` answers. The envelope is a +// string so that no JSON layer between the runtime and here re-encodes the +// bytes whose hash is compared. +type Exported struct { + BindingSeq int64 `json:"binding_seq"` + BindingHash string `json:"binding_hash"` + EnvelopeJSON *string `json:"envelope_json"` +} + +// LoadExported takes the prior from the runtime's export, which must name the +// binding the inventory reports in force before its envelope is read at all. +func LoadExported(inv Inventory, result []byte) (Prior, error) { + var exported Exported + if err := json.Unmarshal(result, &exported); err != nil { + return Prior{}, fmt.Errorf("the runtime's binding export is not readable: %w", err) + } + if exported.BindingSeq != inv.AcceptedBindingSeq || exported.BindingHash != inv.AcceptedBindingHash { + return Prior{}, fmt.Errorf( + "the runtime exported binding %d (%s) and reports binding %d (%s) in "+ + "force; a revision is captured against the binding in force and no other", + exported.BindingSeq, exported.BindingHash, inv.AcceptedBindingSeq, + inv.AcceptedBindingHash) + } + if exported.EnvelopeJSON == nil || *exported.EnvelopeJSON == "" { + return Prior{}, fmt.Errorf("the runtime's binding export carries no envelope") + } + return LoadPrior(inv, []byte(*exported.EnvelopeJSON)) +} + +// Revise captures a change to one zone of the binding in force. +// +// Each fact is shown as the binding in force records it and asked only whether +// it changed; what did not is carried rather than re-typed, and the prior value +// of what did is carried into the reason. The proof is carried only when +// nothing but the rated capacity or the inventory generation changed. Any other +// change, or a like-for-like replacement, needs fresh legs, and those can be +// proven only on a line no zone of the binding in force drives: the proof +// operation refuses such a line. The line is therefore asked first, and a +// change needing fresh legs on a driven line is refused as it is declared. +func Revise( + a Asker, inv Inventory, prior Prior, zoneID string, nowMs int64, +) (binding.Binding, Revision, error) { + at := -1 + names := make([]string, 0, len(prior.Document.Zones)) + driven := map[int]string{} + sensorOf := map[string]string{} + for i, z := range prior.Document.Zones { + names = append(names, z.ZoneID) + if z.ZoneID == zoneID { + at = i + } + if z.Actuator.Kind == binding.KindLocalGPIO && z.Actuator.Identity.GPIOPin != nil { + driven[*z.Actuator.Identity.GPIOPin] = z.ZoneID + } + sensorOf[z.Sensor.SensorID] = z.ZoneID + } + fail := func(err error) (binding.Binding, Revision, error) { + return binding.Binding{}, Revision{}, err + } + if at < 0 { + return fail(fmt.Errorf( + "the binding in force has no zone %q (it has %s); a revision changes a "+ + "zone that is in force", zoneID, strings.Join(quoted(names), ", "))) + } + was := prior.Document.Zones[at] + if was.Actuator.Kind != binding.KindLocalGPIO || was.Actuator.Identity.GPIOPin == nil || + was.Actuator.Identity.ActiveHigh == nil { + return fail(fmt.Errorf( + "zone %q is bound to a %s actuator, and this ceremony revises local_gpio "+ + "zones only", zoneID, was.Actuator.Kind)) + } + state := binding.RetainedState(prior.Accepted)[zoneID] + + rev := Revision{ + Supersedes: inv.AcceptedBindingHash, + SupersedesSeq: inv.AcceptedBindingSeq, + BindingSeq: inv.AcceptedBindingSeq + 1, + ZoneID: zoneID, + Changed: []Change{}, + Carried: []string{}, + CarriedZones: []string{}, + Because: []string{}, + CircuitLegAfterMs: state.ProofAtMs, + ControlLegAfterMs: state.ControlProofAtMs, + TripPointBound: "deferred_to_delivery", + } + a.Say(fmt.Sprintf( + "Revising zone %q of binding %d, the binding in force (%s).\n"+ + "Each fact is shown as that binding records it; answer %q to carry it.\n"+ + "Only a change to the rated capacity or the inventory generation carries "+ + "the proof. Any other change to this zone, or hardware replaced like for "+ + "like, needs fresh legs, and fresh legs can be proven only on a line no "+ + "zone of the binding in force drives: the runtime's proof operation "+ + "refuses a line the binding in force still drives, so such a change on "+ + "one is refused as soon as it is declared.", + zoneID, inv.AcceptedBindingSeq, inv.AcceptedBindingHash, answerUnchanged)) + + why, err := a.Ask("Why is this change being made? It opens the recorded reason.") + if err != nil { + return fail(err) + } + why = strings.TrimSpace(why) + if why == "" || !utf8.ValidString(why) { + return fail(fmt.Errorf( + "a revision records why it was made; the answer was empty or not valid UTF-8")) + } + + now := was + pin := *was.Actuator.Identity.GPIOPin + activeHigh := *was.Actuator.Identity.ActiveHigh + changed := func(fact, before, after string, needsProof bool) error { + rev.Changed = append(rev.Changed, Change{Fact: fact, Was: before, Now: after}) + if !needsProof { + return nil + } + rev.Because = append(rev.Because, fact) + if owner, ok := driven[pin]; ok { + return fmt.Errorf( + "%s changed, so zone %q needs fresh legs, and gpio_pin=%d is still "+ + "driven by zone %q of the binding in force. The runtime's proof "+ + "operation refuses a line the binding in force drives, so this "+ + "revision could never be proven; nothing was written. Taking a "+ + "zone out of operation to prove it afresh is not yet specified", + fact, zoneID, pin, owner) + } + return nil + } + + // The line first: whether fresh legs could ever be proven depends on it. + wasActuator := DescribeActuator(InventoryActuator{ + Kind: was.Actuator.Kind, Identity: map[string]any{"gpio_pin": pin}, + }) + actuatorAnswer, err := askChanged(a, fmt.Sprintf( + "Actuator: %s. Is the protected circuit now controlled by a different "+ + "actuator or control input?", wasActuator), + declaresPin(inv.Actuators, pin), "the device no longer declares that actuator") + if err != nil { + return fail(err) + } + if actuatorAnswer == answerChanged { + act, chooseErr := chooseActuator(a, inv.Actuators) + if chooseErr != nil { + return fail(chooseErr) + } + identity := identityFrom(act, activeHigh) + if act.Kind != binding.KindLocalGPIO || identity.GPIOPin == nil { + return fail(fmt.Errorf( + "%s is not a local_gpio actuator, and this ceremony revises local_gpio "+ + "zones only", DescribeActuator(act))) + } + if *identity.GPIOPin == pin { + return fail(unchangedRefusal("the actuator")) + } + pin = *identity.GPIOPin + if changeErr := changed("actuator", wasActuator, DescribeActuator(act), true); changeErr != nil { + return fail(changeErr) + } + } else { + rev.Carried = append(rev.Carried, "actuator") + } + + // Nothing in the document shows a like-for-like replacement, so it is asked. + replaced, err := a.Choose( + "Was any hardware bound to this zone replaced like for like, with the "+ + "same part on the same pin or input?", + []string{"none", "relay or contactor", "sensor", "both"}) + if err != nil { + return fail(err) + } + if replaced != "none" { + if changeErr := changed("replaced_like_for_like", "as commissioned", + replaced+" replaced", true); changeErr != nil { + return fail(changeErr) + } + } + + sensorAnswer, err := askChanged(a, fmt.Sprintf( + "Sensor: %s. Was it moved to another sensor, or has any of that other than "+ + "its calibration changed?", describeSensor(was.Sensor)), + contains(inv.SensorIDs, was.Sensor.SensorID), "the device no longer declares that sensor") + if err != nil { + return fail(err) + } + if sensorAnswer == answerChanged { + sensorID, chooseErr := a.Choose("Which sensor observes the protected circuit?", sorted(inv.SensorIDs)) + if chooseErr != nil { + return fail(chooseErr) + } + if owner, ok := sensorOf[sensorID]; ok && owner != zoneID { + return fail(fmt.Errorf( + "%s is bound to zone %q of the binding in force; two zones cannot "+ + "name one sensor", sensorID, owner)) + } + if changeErr := changed("sensor", describeSensor(was.Sensor), "", true); changeErr != nil { + return fail(changeErr) + } + sensor, sensorErr := captureSensor(a, sensorID) + if sensorErr != nil { + return fail(sensorErr) + } + if sensor == was.Sensor { + return fail(unchangedRefusal("the sensor")) + } + now.Sensor = sensor + rev.Changed[len(rev.Changed)-1].Now = describeSensor(sensor) + } else { + calAnswer, calErr := askChanged(a, fmt.Sprintf( + "Calibration reference: %q. Was the sensor recalibrated?", + was.Sensor.CalibrationRef), true, "") + if calErr != nil { + return fail(calErr) + } + if calAnswer == answerChanged { + if changeErr := changed("calibration_ref", was.Sensor.CalibrationRef, "", true); changeErr != nil { + return fail(changeErr) + } + ref, askErr := a.Ask("Calibration reference for that sensor:") + if askErr != nil { + return fail(askErr) + } + ref = strings.TrimSpace(ref) + if ref == "" { + return fail(fmt.Errorf( + "a calibration reference is required; it is what an audit follows " + + "back to the instrument")) + } + if ref == was.Sensor.CalibrationRef { + return fail(unchangedRefusal("the calibration reference")) + } + now.Sensor.CalibrationRef = ref + rev.Changed[len(rev.Changed)-1].Now = ref + } else { + rev.Carried = append(rev.Carried, "sensor") + } + } + + // Polarity is shown and asked, never carried silently onto new wiring. + polarityAnswer, err := askChanged(a, fmt.Sprintf( + "Polarity: the driver stage energises the coil when the output is %s.", + levelName(activeHigh)), true, "") + if err != nil { + return fail(err) + } + if polarityAnswer == answerChanged { + if changeErr := changed("active_high", strconv.FormatBool(activeHigh), "", true); changeErr != nil { + return fail(changeErr) + } + level, chooseErr := a.Choose( + "Does the driver stage energise the coil when the output is high or low?", + []string{"high", "low"}) + if chooseErr != nil { + return fail(chooseErr) + } + if (level == "high") == activeHigh { + return fail(unchangedRefusal("the polarity")) + } + activeHigh = level == "high" + rev.Changed[len(rev.Changed)-1].Now = strconv.FormatBool(activeHigh) + } else { + rev.Carried = append(rev.Carried, "active_high") + } + now.Actuator.Identity = binding.Identity{GPIOPin: &pin, ActiveHigh: &activeHigh} + + mappingAnswer, err := askChanged(a, fmt.Sprintf( + "Commissioned mapping: %s.", describeMapping(was.Actuator.Mapping)), true, "") + if err != nil { + return fail(err) + } + if mappingAnswer == answerChanged { + if changeErr := changed("commissioned_mapping", describeMapping(was.Actuator.Mapping), "", true); changeErr != nil { + return fail(changeErr) + } + mapping, mapErr := captureMapping(a) + if mapErr != nil { + return fail(mapErr) + } + if mapping == was.Actuator.Mapping { + return fail(unchangedRefusal("the mapping")) + } + now.Actuator.Mapping = mapping + rev.Changed[len(rev.Changed)-1].Now = describeMapping(mapping) + } else { + rev.Carried = append(rev.Carried, "commissioned_mapping") + } + + capacityAnswer, err := askChanged(a, fmt.Sprintf( + "Rated capacity: %gA, from the %s.", was.RatedCapacity.Value, + was.RatedCapacity.Provenance), true, "") + if err != nil { + return fail(err) + } + if capacityAnswer == answerChanged { + provenance, chooseErr := a.Choose( + "Where does the rated capacity come from?", + []string{"nameplate", "installer_measured", "design_document"}) + if chooseErr != nil { + return fail(chooseErr) + } + value, askErr := askFloat(a, "Rated capacity of the protected circuit, in amperes:") + if askErr != nil { + return fail(askErr) + } + capacity := binding.RatedCapacity{ + Parameter: was.RatedCapacity.Parameter, Value: value, Provenance: provenance, + } + if capacity == was.RatedCapacity { + return fail(unchangedRefusal("the rated capacity")) + } + now.RatedCapacity = capacity + _ = changed("rated_capacity", + fmt.Sprintf("%gA (%s)", was.RatedCapacity.Value, was.RatedCapacity.Provenance), + fmt.Sprintf("%gA (%s)", value, provenance), false) + } else { + rev.Carried = append(rev.Carried, "rated_capacity") + } + // Re-bounds-checked whether or not it changed: the sensor it is bounded by + // may have. The trip point is not: its multiplier is the release's, and only + // delivery applies it. + if now.RatedCapacity.Value <= 0 || now.RatedCapacity.Value > now.Sensor.RangeMax { + return fail(fmt.Errorf( + "a rated capacity of %gA is outside what a sensor with a full scale of "+ + "%gA can observe", now.RatedCapacity.Value, now.Sensor.RangeMax)) + } + + generation := prior.Document.InventoryGeneration + generationAnswer, err := askChanged(a, fmt.Sprintf( + "Inventory generation this binding is made against: %d.", generation), true, "") + if err != nil { + return fail(err) + } + if generationAnswer == answerChanged { + value, askErr := askInt(a, "Inventory generation this binding is made against:") + if askErr != nil { + return fail(askErr) + } + if value < 1 { + return fail(fmt.Errorf( + "an inventory generation is at least 1; %d names no inventory", value)) + } + if value == generation { + return fail(unchangedRefusal("the inventory generation")) + } + // Generations are monotonic per device, so one below the binding in + // force names an inventory the device has already left. + if value < generation { + return fail(fmt.Errorf( + "inventory generation %d is below the %d the binding in force was "+ + "made against; generations only increase", value, generation)) + } + _ = changed("inventory_generation", strconv.FormatInt(generation, 10), + strconv.FormatInt(value, 10), false) + generation = value + } else { + rev.Carried = append(rev.Carried, "inventory_generation") + } + + rev.FreshProof = len(rev.Because) > 0 + if rev.FreshProof { + // Reached only on a line no zone of the binding in force drives. + a.Say(fmt.Sprintf( + "This revision changes %s, so zone %q cannot inherit the proof in force.\n"+ + "It needs a fresh circuit leg performed after %d. The control leg in "+ + "force%s is not carried: once this binding is delivered and the runtime "+ + "restarts, prove both outcomes on gpio_pin=%d and export a fresh control "+ + "leg. Until then the zone is provisional.", + strings.Join(rev.Because, ", "), zoneID, state.ProofAtMs, + controlLegClause(state.ControlProofAtMs), pin)) + if inv.DeploymentPosture != "development" { + a.Say(fmt.Sprintf( + "This device verifies under %s posture, which refuses an "+ + "undemonstrated circuit leg.", inv.DeploymentPosture)) + } + proof, proofErr := captureProof(a, now.Actuator.Mapping, nowMs, state.ProofAtMs) + if proofErr != nil { + return fail(proofErr) + } + now.Proof = proof + rev.CircuitLeg = "fresh" + if proof.Method == binding.MethodUnproven { + rev.CircuitLeg = StateUndemonstrated + } + rev.ControlLeg = "prove_after_delivery" + } else { + a.Say(fmt.Sprintf( + "Nothing this revision changes invalidates the proof, so zone %q carries "+ + "both legs of the binding in force.", zoneID)) + rev.Carried = append(rev.Carried, "proof") + rev.CircuitLeg = "carried" + rev.ControlLeg = "carried" + } + rev.ProofState = ProofState(now.Proof) + rev.Reason = composeReason(why, rev) + + zones := make([]binding.Zone, len(prior.Document.Zones)) + copy(zones, prior.Document.Zones) + zones[at] = now + for _, z := range zones { + if z.ZoneID != zoneID { + rev.CarriedZones = append(rev.CarriedZones, z.ZoneID) + } + } + hash := inv.AcceptedBindingHash + draft := binding.Binding{ + V: 1, + BindingSeq: inv.AcceptedBindingSeq + 1, + DeviceID: inv.DeviceID, + InventoryGeneration: generation, + Supersedes: &hash, + Reason: rev.Reason, + Zones: zones, + } + return draft, rev, nil +} + +// composeReason is the installer's why, then the prior value of everything the +// revision changed, so the document says what it replaced as well as why. +func composeReason(why string, rev Revision) string { + parts := make([]string, 0, len(rev.Changed)) + for _, c := range rev.Changed { + parts = append(parts, fmt.Sprintf("%s was %s, now %s", c.Fact, c.Was, c.Now)) + } + changes := "nothing changed" + if len(parts) > 0 { + changes = strings.Join(parts, "; ") + } + return fmt.Sprintf("%s. Revises binding %d (%s), zone %q: %s.", + strings.TrimSuffix(why, "."), rev.SupersedesSeq, rev.Supersedes, rev.ZoneID, changes) +} + +// ProofState names what a zone's proof establishes: both legs, the circuit leg +// alone, or nothing. +func ProofState(p binding.Proof) string { + if p.Method == binding.MethodUnproven { + return StateUndemonstrated + } + if p.ControlPath != nil && p.ControlPath.Method == binding.ControlCommanded { + return StateProven + } + return StateProvisional +} + +// DeclaredRefs is the inventory in the verifier's terms. +func DeclaredRefs(inv Inventory) ([]binding.ActuatorRef, error) { + refs := make([]binding.ActuatorRef, 0, len(inv.Actuators)) + for _, act := range inv.Actuators { + ref := binding.ActuatorRef{Kind: act.Kind} + switch act.Kind { + case binding.KindLocalGPIO: + pin, ok := act.Identity["gpio_pin"].(float64) + if !ok || pin != float64(int64(pin)) { + return nil, fmt.Errorf("the inventory names %s, whose pin is not a whole number", + DescribeActuator(act)) + } + ref.GPIOPin = int64(pin) + case binding.KindFirmware: + device, ok1 := act.Identity["firmware_device_id"].(string) + channel, ok2 := act.Identity["channel"].(string) + if !ok1 || !ok2 { + return nil, fmt.Errorf("the inventory names %s, which is not a firmware channel identity", + DescribeActuator(act)) + } + ref.FirmwareDeviceID, ref.Channel = device, channel + default: + return nil, fmt.Errorf("the inventory names an actuator of kind %q, which this build does not know", + act.Kind) + } + refs = append(refs, ref) + } + return refs, nil +} + +// askChanged offers "changed" alone when the value in force can no longer be +// carried, and says why. +func askChanged(a Asker, prompt string, carriable bool, why string) (string, error) { + if !carriable { + a.Say(fmt.Sprintf("%s cannot be carried: %s.", strings.TrimSuffix(prompt, "."), why)) + return a.Choose(prompt, []string{answerChanged}) + } + return a.Choose(prompt, []string{answerUnchanged, answerChanged}) +} + +func unchangedRefusal(what string) error { + return fmt.Errorf( + "%s was answered changed and then given the value in force; one of those "+ + "two answers describes the site wrongly", what) +} + +func controlLegClause(at *int64) string { + if at == nil { + return "" + } + return fmt.Sprintf(" (performed at %d)", *at) +} + +func describeSensor(s binding.Sensor) string { + return fmt.Sprintf("%s, %s in %s, %s, range %g to %g, noise floor %g, calibration %q", + s.SensorID, s.Quantity, s.Unit, s.Direction, s.RangeMin, s.RangeMax, + s.NoiseFloor, s.CalibrationRef) +} + +func describeMapping(m binding.Mapping) string { + return fmt.Sprintf("open needs the coil %s, close needs it %s, de-energised the circuit is %s", + m.OpenProtectedCircuit, m.CloseProtectedCircuit, m.DeEnergisedTerminalState) +} + +func levelName(activeHigh bool) string { + if activeHigh { + return "high" + } + return "low" +} + +func declaresPin(actuators []InventoryActuator, pin int) bool { + for _, act := range actuators { + if act.Kind != binding.KindLocalGPIO { + continue + } + if value, ok := act.Identity["gpio_pin"].(float64); ok && value == float64(pin) { + return true + } + } + return false +} + +func contains(values []string, want string) bool { + for _, v := range values { + if v == want { + return true + } + } + return false +} + +func quoted(values []string) []string { + out := make([]string, 0, len(values)) + for _, v := range values { + out = append(out, strconv.Quote(v)) + } + sort.Strings(out) + return out +} diff --git a/internal/capture/terminal.go b/internal/capture/terminal.go index a77a20e..56d76cc 100644 --- a/internal/capture/terminal.go +++ b/internal/capture/terminal.go @@ -40,6 +40,11 @@ func (t *TerminalAsker) Ask(prompt string) (string, error) { return strings.TrimSpace(line), nil } +// Say writes text the installer reads before the next question. +func (t *TerminalAsker) Say(text string) { + fmt.Fprintf(t.Out, "\n%s\n", text) +} + // Choose offers exactly the options given and accepts nothing else. // // An unrecognised answer is re-asked rather than resolved to the nearest