docs: rewrite features.md, audit README + architecture against repo

Rewrote docs/features.md from scratch as authoritative feature inventory
(1255 lines, every claim verified against source files).

Audited README.md and architecture.md against repo — fixed 19 stale
references: K8s Secrets status, issuer counts, dashboard page counts,
CI thresholds, missing connectors in Mermaid diagrams, OpenAPI operation
count, GetCACertPEM behavior, and V2/V4 roadmap accuracy.

Also includes related fixes discovered during audit:
- Scheduler skips expired/failed/revoked certs from auto-renewal
- Seed demo expiry dates moved outside 31-day scheduler query window
- Agent pages use correct last_heartbeat_at field name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-04-15 00:22:57 -04:00
parent 3da6584ab8
commit c015cab2f4
9 changed files with 1165 additions and 1314 deletions
+11 -2
View File
@@ -136,8 +136,17 @@ func (s *RenewalService) CheckExpiringCertificates(ctx context.Context) error {
policyCache := make(map[string]*domain.RenewalPolicy)
for _, cert := range expiring {
// Skip if already renewing or archived
if cert.Status == domain.CertificateStatusRenewalInProgress || cert.Status == domain.CertificateStatusArchived {
// Skip certs in terminal or non-renewable states:
// - RenewalInProgress: already being renewed
// - Archived: no longer managed
// - Revoked: intentionally revoked, should not be auto-renewed
// - Failed: requires manual intervention (the failure cause hasn't been resolved)
// - Expired: requires manual review (why did it expire without renewal?)
if cert.Status == domain.CertificateStatusRenewalInProgress ||
cert.Status == domain.CertificateStatusArchived ||
cert.Status == domain.CertificateStatusRevoked ||
cert.Status == domain.CertificateStatusFailed ||
cert.Status == domain.CertificateStatusExpired {
continue
}
+71
View File
@@ -239,6 +239,77 @@ func TestCheckExpiringCertificates_SkipsRenewalInProgress(t *testing.T) {
}
}
func TestCheckExpiringCertificates_SkipsExpiredFailedRevoked(t *testing.T) {
ctx := context.Background()
// Test that certs in Expired, Failed, and Revoked states do not get renewal jobs
for _, tc := range []struct {
name string
status domain.CertificateStatus
}{
{"Expired", domain.CertificateStatusExpired},
{"Failed", domain.CertificateStatusFailed},
{"Revoked", domain.CertificateStatusRevoked},
} {
t.Run(tc.name, func(t *testing.T) {
certRepo := newMockCertificateRepository()
jobRepo := newMockJobRepository()
policyRepo := newMockRenewalPolicyRepository()
auditRepo := newMockAuditRepository()
notifRepo := newMockNotificationRepository()
auditSvc := NewAuditService(auditRepo)
notifSvc := NewNotificationService(notifRepo, map[string]Notifier{})
issuerRegistry := NewIssuerRegistry(slog.Default())
issuerRegistry.Set("iss-test", &mockIssuerConnector{})
svc := NewRenewalService(certRepo, jobRepo, policyRepo, nil, auditSvc, notifSvc, issuerRegistry, "server")
cert := &domain.ManagedCertificate{
ID: "mc-" + strings.ToLower(string(tc.status)),
Name: "Test " + string(tc.status),
CommonName: "test.example.com",
SANs: []string{},
OwnerID: "owner-1",
TeamID: "team-1",
IssuerID: "iss-test",
RenewalPolicyID: "rp-standard",
Status: tc.status,
ExpiresAt: time.Now().AddDate(0, 0, 10),
Tags: make(map[string]string),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
certRepo.AddCert(cert)
policy := &domain.RenewalPolicy{
ID: "rp-standard",
Name: "Standard",
RenewalWindowDays: 30,
AutoRenew: true,
MaxRetries: 3,
RetryInterval: 300,
AlertThresholdsDays: []int{30, 14, 7, 0},
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
policyRepo.AddPolicy(policy)
err := svc.CheckExpiringCertificates(ctx)
if err != nil {
t.Fatalf("CheckExpiringCertificates failed: %v", err)
}
for _, job := range jobRepo.Jobs {
if job.Type == domain.JobTypeRenewal {
t.Errorf("should not create renewal job for cert with %s status", tc.status)
}
}
})
}
}
func TestCheckExpiringCertificates_UpdatesStatusToExpiring(t *testing.T) {
t.Helper()
ctx := context.Background()