diff --git a/.ciagent/CHECKPOINT.json b/.ciagent/CHECKPOINT.json index acf64da..8cd9b47 100644 --- a/.ciagent/CHECKPOINT.json +++ b/.ciagent/CHECKPOINT.json @@ -1,31 +1,21 @@ { - "phase": 0, + "phase": 1, "stage": "complete", "milestone": "v0.13", "milestone_slug": "production-hardening-2", - "phase_role": "pre_execution", + "phase_role": "execution", "attempts": 0, - "updated_at": "2026-08-07T19:20:00Z", + "updated_at": "2026-08-07T19:05:00Z", "milestone_complete": false, "previous_milestone": "v0.12", "phase_count": 14, - "phases_shipped": ["P0"], - "tags_shipped": ["v0.12.0"], + "phases_shipped": ["P0", "P1"], + "tags_shipped": ["v0.12.0", "v0.12.1"], "requirements": { - "covered": [], + "covered": [149], "partial": [] }, - "binding_conditions": [ - "C-39", "C-40", "C-41", "C-42", "C-43", - "C-44", "C-45", "C-46", "C-47", "C-48", "C-49" - ], + "binding_conditions": ["C-39","C-40","C-41","C-42","C-43","C-44","C-45","C-46","C-47","C-48","C-49"], "load_bearing_rule": "R-022", - "next_milestone": "v1.0", - "grill_verdict": "CONDITIONAL_PROCEED", - "grill_confidence": 0.82, - "ship": { - "tag": "v0.12.0", - "merged_to_milestone": true, - "milestone_release": null - } + "next_milestone": "v1.0" } diff --git a/go.mod b/go.mod index 001c16e..7af21bb 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.cloudinit.dev/coreci/orca -go 1.25.0 +go 1.25.12 require ( github.com/coreos/go-oidc/v3 v3.20.0 diff --git a/internal/cli/acl.go b/internal/cli/acl.go index 65511a2..b2aebac 100644 --- a/internal/cli/acl.go +++ b/internal/cli/acl.go @@ -59,7 +59,7 @@ func parseIdentity(raw string) (acl.Identity, error) { if raw == "" { return acl.Identity{}, fmt.Errorf("identity is empty") } - return acl.Identity{Kind: acl.KindToken, ID: raw}, nil + return acl.Identity{Kind: acl.KindOidc, ID: raw}, nil } // parsePermissions parses a comma-separated list of "read","write", diff --git a/internal/cli/acl_test.go b/internal/cli/acl_test.go index 5f92faa..7558a3d 100644 --- a/internal/cli/acl_test.go +++ b/internal/cli/acl_test.go @@ -55,13 +55,13 @@ func TestParseIdentity_Spiffe(t *testing.T) { } } -func TestParseIdentity_Token(t *testing.T) { +func TestParseIdentity_Oidc(t *testing.T) { id, err := parseIdentity("operator-1") if err != nil { t.Fatalf("parseIdentity: %v", err) } - if id.Kind != "token" { - t.Errorf("kind = %q, want token", id.Kind) + if id.Kind != "oidc" { + t.Errorf("kind = %q, want oidc", id.Kind) } if id.ID != "operator-1" { t.Errorf("id = %q, want operator-1", id.ID) diff --git a/internal/cli/init_test.go b/internal/cli/init_test.go index fdc209f..3bbc1ed 100644 --- a/internal/cli/init_test.go +++ b/internal/cli/init_test.go @@ -80,8 +80,8 @@ func TestInit_FullBootstrap(t *testing.T) { if err != nil { t.Fatalf("migration version: %v", err) } - if version != "0007_certs_serial_unique.sql" { - t.Errorf("migration version = %q, want 0007_certs_serial_unique.sql", version) + if version != "0008_audit_tamper_evidence.sql" { + t.Errorf("migration version = %q, want 0008_audit_tamper_evidence.sql", version) } // Verify localhost node registered with kind=localhost. diff --git a/internal/doctor/doctor.go b/internal/doctor/doctor.go index 61ef7cd..2556e21 100644 --- a/internal/doctor/doctor.go +++ b/internal/doctor/doctor.go @@ -121,6 +121,10 @@ func CertCA() Check { Description: "CA at ~/.orca with mode 0600/0644 (REQ-033)", Run: func(_ context.Context) (Result, string) { dir := certpaths.Dir() + caCert := certpaths.CACertPath() + if _, err := os.Stat(caCert); err != nil { + return ResultFail, fmt.Sprintf("CA cert missing: %v", err) + } if err := security.EnforceFileModes(dir); err != nil { return ResultFail, err.Error() } diff --git a/tests/integration/scenarios_test.go b/tests/integration/scenarios_test.go index ed9e1a4..cbbd8b4 100644 --- a/tests/integration/scenarios_test.go +++ b/tests/integration/scenarios_test.go @@ -273,7 +273,7 @@ func TestScenario_ACL(t *testing.T) { t.Fatalf("mkdir cluster dir: %v", err) } a := acl.NewACL() - id := acl.Identity{Kind: acl.KindToken, ID: "operator-1"} + id := acl.Identity{Kind: acl.KindOidc, ID: "operator-1"} a.Grant(id, "prod", acl.PermRead|acl.PermWrite) if !a.Check(id, "prod", acl.PermRead) { t.Error("expected read on prod after grant") @@ -287,7 +287,7 @@ func TestScenario_ACL(t *testing.T) { if a.Check(id, "staging", acl.PermRead) { t.Error("cross-ns read should be denied") } - admin := acl.Identity{Kind: acl.KindToken, ID: "root"} + admin := acl.Identity{Kind: acl.KindOidc, ID: "root"} a.Grant(admin, "prod", acl.PermAdmin) if !a.Check(admin, "prod", acl.PermRead) { t.Error("admin should imply read") @@ -303,7 +303,7 @@ func TestScenario_ACL(t *testing.T) { if err != nil { t.Fatalf("marshal acl: %v", err) } - if err := writeAtomic(paths.ACLPath(), data, 0o644); err != nil { + if err := writeAtomic(paths.ACLPath(), data, 0o600); err != nil { t.Fatalf("write acl.json: %v", err) } loaded, err := os.ReadFile(paths.ACLPath())