oficina / home Public

Add empty operator consumer pointers and verification history schema

Paul Campbell pushed by paul@keymail.dev 75a16d6110aaaf22121df138902e52e355076f21 parent e26bee7
2 files changed, +55 −0
  • internal/home/directorydata/operator_migrations/migrations/0001_operator_bindings.sql +34 −0
  • internal/home/directorydata/operator_schema.go +21 −0
diff --git a/internal/home/directorydata/operator_migrations/migrations/0001_operator_bindings.sql b/internal/home/directorydata/operator_migrations/migrations/0001_operator_bindings.sql
new file mode 100644
index 0000000..5cec2d7
--- /dev/null
+++ b/internal/home/directorydata/operator_migrations/migrations/0001_operator_bindings.sql
@@ -0,0 +1,34 @@
+CREATE TABLE directory_operator_consumer_records (
+ consumer_id TEXT PRIMARY KEY REFERENCES roster_consumers(consumer_id),
+ operation_id TEXT NOT NULL UNIQUE REFERENCES roster_operator_receipts(operation_id),
+ sequence INTEGER NOT NULL CHECK(typeof(sequence)='integer' AND sequence>0),
+ generation TEXT NOT NULL CHECK(length(generation)=43),
+ record_digest BLOB NOT NULL CHECK(typeof(record_digest)='blob' AND length(record_digest)=32)
+);
+CREATE TABLE verification_attempts (
+ operation_id TEXT PRIMARY KEY CHECK(length(operation_id)=43),
+ consumer_id TEXT NOT NULL REFERENCES roster_consumers(consumer_id),
+ team_id INTEGER NOT NULL REFERENCES teams(id),
+ app TEXT NOT NULL,
+ origin TEXT NOT NULL,
+ generation TEXT NOT NULL CHECK(length(generation)=43),
+ record_sequence INTEGER NOT NULL CHECK(typeof(record_sequence)='integer' AND record_sequence>0),
+ record_digest BLOB NOT NULL CHECK(typeof(record_digest)='blob' AND length(record_digest)=32),
+ expected_epoch INTEGER NOT NULL CHECK(typeof(expected_epoch)='integer' AND expected_epoch>0),
+ owner_ref TEXT NOT NULL CHECK(length(owner_ref)=29),
+ issued_at INTEGER NOT NULL CHECK(typeof(issued_at)='integer' AND issued_at>0),
+ expires_at INTEGER NOT NULL CHECK(typeof(expires_at)='integer' AND expires_at>issued_at AND expires_at-issued_at<=600),
+ authorization_digest BLOB NOT NULL CHECK(typeof(authorization_digest)='blob' AND length(authorization_digest)=32)
+);
+CREATE TABLE verification_active (
+ consumer_id TEXT PRIMARY KEY REFERENCES roster_consumers(consumer_id),
+ operation_id TEXT NOT NULL UNIQUE REFERENCES verification_attempts(operation_id)
+);
+CREATE TABLE verification_outcomes (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ attempt_id TEXT NOT NULL REFERENCES verification_attempts(operation_id),
+ operator_operation_id TEXT NOT NULL CHECK(length(operator_operation_id)=43),
+ kind TEXT NOT NULL CHECK(kind IN ('opened','expired','activated')),
+ completed_at INTEGER NOT NULL CHECK(typeof(completed_at)='integer' AND completed_at>0),
+ UNIQUE(attempt_id,operator_operation_id,kind)
+);
diff --git a/internal/home/directorydata/operator_schema.go b/internal/home/directorydata/operator_schema.go
new file mode 100644
index 0000000..357ecae
--- /dev/null
+++ b/internal/home/directorydata/operator_schema.go
@@ -0,0 +1,21 @@
+package directorydata
+
+import (
+ "embed"
+ "io/fs"
+
+ "github.com/carlosframework/rastrillo/migrate"
+)
+
+//go:embed operator_migrations
+var operatorMigrations embed.FS
+
+// OperatorSchema adds empty provisioning pointers and verification history.
+// No migration creates authority or opens a pending consumer window.
+var OperatorSchema = func() *migrate.Set {
+ f, e := fs.Sub(operatorMigrations, "operator_migrations")
+ if e != nil {
+ panic(e)
+ }
+ return migrate.MustFromFS(f, "oficina_directory_operator_bindings")
+}()