carlos / platform Public

console: inert claim-operation adapters and construction fields (claim Plan 5 Task 4)

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
codex agent, operated by paul@keymail.dev pushed by claude agent, operated by paul@keymail.dev e5ff37a045d94d75838531fc9ec712bc5badf204 parent 48db5f0
2 files changed, +67 −0
  • internal/console/hostclaimops.go +63 −0
  • internal/console/server.go +4 −0

CI passed — run details

diff --git a/internal/console/hostclaimops.go b/internal/console/hostclaimops.go
new file mode 100644
index 000000000..1f70ef3f1
--- /dev/null
+++ b/internal/console/hostclaimops.go
@@ -0,0 +1,63 @@
+package console
+
+import (
+ "context"
+ "log"
+ "time"
+
+ "github.com/carlosframework/platform/internal/hostclaim"
+ "github.com/carlosframework/platform/internal/hostops"
+ "github.com/carlosframework/platform/internal/provision"
+)
+
+func (s *Server) retireHostRecord(ctx context.Context, ref provision.RetireRef) error {
+ var claims provision.ClaimRetirer
+ if s.cfg.HostClaimOps != nil {
+ claims = s.cfg.HostClaimOps
+ }
+ return provision.RetireRecord(ctx, s.cfg.Releases, ref, provision.RetireOptions{HostClaim: s.cfg.HostClaim, Claims: claims})
+}
+func (s *Server) adoptHostRecord(ctx context.Context, key string) (hostclaim.Observed, error) {
+ if !s.cfg.HostClaim || s.cfg.HostClaimOps == nil {
+ return hostclaim.Observed{}, hostops.ErrContract
+ }
+ rec, err := hostops.ReadRecord(ctx, s.cfg.Releases, key)
+ if err != nil {
+ return hostclaim.Observed{}, err
+ }
+ return s.cfg.HostClaimOps.Adopt(ctx, rec)
+}
+
+const claimRecoveryInterval = 2 * time.Minute
+
+// Called by serve, never NewServer. Tests can invoke the one-pass method.
+func (s *Server) StartClaimRecoveryPass(ctx context.Context) {
+ if !s.cfg.HostClaim {
+ return
+ }
+ if s.cfg.HostClaimRecovery == nil {
+ log.Printf("console: claim recovery: %v", hostops.ErrContract)
+ return
+ }
+ t := time.NewTicker(claimRecoveryInterval)
+ defer t.Stop()
+ for {
+ if err := s.claimRecoveryPass(ctx); err != nil {
+ log.Printf("console: claim recovery: %v", err)
+ }
+ select {
+ case <-ctx.Done():
+ return
+ case <-t.C:
+ }
+ }
+}
+func (s *Server) claimRecoveryPass(ctx context.Context) error {
+ if !s.cfg.HostClaim {
+ return nil
+ }
+ if s.cfg.HostClaimRecovery == nil {
+ return hostops.ErrContract
+ }
+ return s.cfg.HostClaimRecovery.Pass(ctx)
+}
diff --git a/internal/console/server.go b/internal/console/server.go
index 9e1fb9cdc..68426e7c2 100644
--- a/internal/console/server.go
+++ b/internal/console/server.go
@@ -13,6 +13,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "github.com/carlosframework/platform/internal/hostops"
"github.com/carlosframework/platform/internal/lease"
"html/template"
"log"
@@ -456,6 +457,9 @@ const (
// Config is everything the server reads its world through.
type Config struct {
+ HostClaimOps *hostops.Controller
+ HostClaimRecovery *hostops.Recovery
+
HostClaim bool
DBVersions lease.VersionedStore
Origin string // the console's public origin — the OAuth client_id