up
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Build Test Deploy / docs (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / deploy (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / build-test (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / authority-container (push) Has been cancelled
				
			
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Build Test Deploy / docs (push) Has been cancelled
				
			Build Test Deploy / deploy (push) Has been cancelled
				
			Build Test Deploy / build-test (push) Has been cancelled
				
			Build Test Deploy / authority-container (push) Has been cancelled
				
			Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		| @@ -10,6 +10,12 @@ passwordPolicy: | ||||
|   requireDigit: true | ||||
|   requireSymbol: true | ||||
|  | ||||
| passwordHashing: | ||||
|   algorithm: "Argon2id" | ||||
|   memorySizeInKib: 19456 | ||||
|   iterations: 2 | ||||
|   parallelism: 1 | ||||
|  | ||||
| lockout: | ||||
|   enabled: true | ||||
|   maxAttempts: 5 | ||||
|   | ||||
| @@ -23,6 +23,25 @@ storage: | ||||
|   # databaseName: "stellaops_authority" | ||||
|   commandTimeout: "00:00:30" | ||||
|  | ||||
| # Signing configuration for revocation bundles and JWKS. | ||||
| signing: | ||||
|   enabled: true | ||||
|   activeKeyId: "authority-signing-2025-dev" | ||||
|   keyPath: "../certificates/authority-signing-2025-dev.pem" | ||||
|   algorithm: "ES256" | ||||
|   keySource: "file" | ||||
|   # provider: "default" | ||||
|   additionalKeys: | ||||
|     - keyId: "authority-signing-dev" | ||||
|       path: "../certificates/authority-signing-dev.pem" | ||||
|       source: "file" | ||||
|   # Rotation flow: | ||||
|   #   1. Generate a new PEM under ./certificates (e.g. authority-signing-2026-dev.pem). | ||||
|   #   2. Trigger the .gitea/workflows/authority-key-rotation.yml workflow (or run | ||||
|   #      ops/authority/key-rotation.sh) with the new keyId/keyPath. | ||||
|   #   3. Update activeKeyId/keyPath above and move the previous key into additionalKeys | ||||
|   #      so restarts retain retired material for JWKS consumers. | ||||
|  | ||||
| # Bootstrap administrative endpoints (initial provisioning). | ||||
| bootstrap: | ||||
|   enabled: false | ||||
|   | ||||
							
								
								
									
										165
									
								
								etc/authority/revocation_bundle.schema.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								etc/authority/revocation_bundle.schema.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| { | ||||
|   "$schema": "https://json-schema.org/draft/2020-12/schema", | ||||
|   "$id": "https://stella-ops.org/schemas/revocation-bundle.json", | ||||
|   "title": "StellaOps Authority Revocation Bundle", | ||||
|   "description": "Canonical representation of revoked tokens, clients, and principals distributed to offline mirrors.", | ||||
|   "type": "object", | ||||
|   "additionalProperties": false, | ||||
|   "required": [ | ||||
|     "schemaVersion", | ||||
|     "issuer", | ||||
|     "issuedAt", | ||||
|     "sequence", | ||||
|     "revocations" | ||||
|   ], | ||||
|   "properties": { | ||||
|     "schemaVersion": { | ||||
|       "type": "string", | ||||
|       "pattern": "^1\\.0\\.[0-9]+$", | ||||
|       "description": "SemVer of the bundle schema. Major version bumps indicate breaking changes." | ||||
|     }, | ||||
|     "issuer": { | ||||
|       "type": "string", | ||||
|       "format": "uri", | ||||
|       "description": "Canonical issuer URL of the Authority instance producing the bundle." | ||||
|     }, | ||||
|     "bundleId": { | ||||
|       "type": "string", | ||||
|       "pattern": "^[a-f0-9]{16,64}$", | ||||
|       "description": "Deterministic identifier for this bundle revision (e.g. SHA-256 hex)." | ||||
|     }, | ||||
|     "issuedAt": { | ||||
|       "type": "string", | ||||
|       "format": "date-time", | ||||
|       "description": "UTC timestamp when the bundle was emitted." | ||||
|     }, | ||||
|     "validFrom": { | ||||
|       "type": "string", | ||||
|       "format": "date-time", | ||||
|       "description": "UTC timestamp when consumers should begin enforcing entries." | ||||
|     }, | ||||
|     "expiresAt": { | ||||
|       "type": "string", | ||||
|       "format": "date-time", | ||||
|       "description": "Optional expiry after which consumers must fetch a newer bundle." | ||||
|     }, | ||||
|     "sequence": { | ||||
|       "type": "integer", | ||||
|       "minimum": 0, | ||||
|       "description": "Monotonic sequence number. Consumers MUST ignore bundles with lower sequence values." | ||||
|     }, | ||||
|     "signingKeyId": { | ||||
|       "type": "string", | ||||
|       "description": "Key identifier (kid) used for the detached JWS signature." | ||||
|     }, | ||||
|     "revocations": { | ||||
|       "type": "array", | ||||
|       "description": "Deterministically sorted revocation entries.", | ||||
|       "items": { "$ref": "#/$defs/revocationEntry" } | ||||
|     }, | ||||
|     "metadata": { | ||||
|       "type": "object", | ||||
|       "description": "Additional producer metadata (operator, environment, export job id).", | ||||
|       "additionalProperties": { | ||||
|         "type": ["string", "number", "boolean", "null"] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "$defs": { | ||||
|     "revocationEntry": { | ||||
|       "type": "object", | ||||
|       "additionalProperties": false, | ||||
|       "required": ["id", "category", "revokedAt"], | ||||
|       "properties": { | ||||
|         "id": { | ||||
|           "type": "string", | ||||
|           "minLength": 4, | ||||
|           "description": "Primary identifier for the revoked entity (token id, subject id, client id, or key id)." | ||||
|         }, | ||||
|         "category": { | ||||
|           "type": "string", | ||||
|           "enum": ["token", "subject", "client", "key"], | ||||
|           "description": "Scope of the revocation entry." | ||||
|         }, | ||||
|         "tokenType": { | ||||
|           "type": "string", | ||||
|           "enum": [ | ||||
|             "access_token", | ||||
|             "refresh_token", | ||||
|             "authorization_code", | ||||
|             "device_code" | ||||
|           ], | ||||
|           "description": "Token type impacted by the revocation (required when category == 'token')." | ||||
|         }, | ||||
|         "subjectId": { | ||||
|           "type": "string", | ||||
|           "description": "Subject identifier impacted (user, service account)." | ||||
|         }, | ||||
|         "clientId": { | ||||
|           "type": "string", | ||||
|           "description": "OAuth client identifier impacted." | ||||
|         }, | ||||
|         "reason": { | ||||
|           "type": "string", | ||||
|           "pattern": "^[a-z0-9_.-]{1,64}$", | ||||
|           "description": "Reason code (e.g. compromised, rotation, policy)." | ||||
|         }, | ||||
|         "reasonDescription": { | ||||
|           "type": "string", | ||||
|           "maxLength": 256, | ||||
|           "description": "Human-readable description for operator tooling." | ||||
|         }, | ||||
|         "revokedAt": { | ||||
|           "type": "string", | ||||
|           "format": "date-time", | ||||
|           "description": "UTC timestamp when the entity was revoked." | ||||
|         }, | ||||
|         "effectiveAt": { | ||||
|           "type": "string", | ||||
|           "format": "date-time", | ||||
|           "description": "UTC timestamp when revocation becomes effective (defaults to revokedAt)." | ||||
|         }, | ||||
|         "expiresAt": { | ||||
|           "type": "string", | ||||
|           "format": "date-time", | ||||
|           "description": "Optional expiry after which the revocation no longer applies." | ||||
|         }, | ||||
|         "scopes": { | ||||
|           "type": "array", | ||||
|           "items": { "type": "string" }, | ||||
|           "uniqueItems": true, | ||||
|           "description": "Scoped permissions affected (for token revocations)." | ||||
|         }, | ||||
|         "fingerprint": { | ||||
|           "type": "string", | ||||
|           "pattern": "^[A-Fa-f0-9]{64}$", | ||||
|           "description": "SHA-256 hash of the revoked credential (optional)." | ||||
|         }, | ||||
|         "metadata": { | ||||
|           "type": "object", | ||||
|           "description": "Additional structured metadata to assist consumers (e.g. audit id).", | ||||
|           "patternProperties": { | ||||
|             "^[a-zA-Z0-9_.-]{1,64}$": { | ||||
|               "type": ["string", "number", "boolean", "null"] | ||||
|             } | ||||
|           }, | ||||
|           "additionalProperties": false | ||||
|         } | ||||
|       }, | ||||
|       "allOf": [ | ||||
|         { | ||||
|           "if": { "properties": { "category": { "const": "token" } } }, | ||||
|           "then": { "required": ["tokenType", "clientId"] } | ||||
|         }, | ||||
|         { | ||||
|           "if": { "properties": { "category": { "const": "subject" } } }, | ||||
|           "then": { "required": ["subjectId"] } | ||||
|         }, | ||||
|         { | ||||
|           "if": { "properties": { "category": { "const": "client" } } }, | ||||
|           "then": { "required": ["clientId"] } | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -59,7 +59,27 @@ authority: | ||||
|   clientSecretFile: "" | ||||
|   clientScopes: | ||||
|     - "feedser.jobs.trigger" | ||||
|   resilience: | ||||
|     # Enable deterministic retry/backoff when Authority is briefly unavailable. | ||||
|     enableRetries: true | ||||
|     retryDelays: | ||||
|       - "00:00:01" | ||||
|       - "00:00:02" | ||||
|       - "00:00:05" | ||||
|     # Allow stale discovery/JWKS responses when Authority is offline (extend tolerance as needed for air-gapped mirrors). | ||||
|     allowOfflineCacheFallback: true | ||||
|     offlineCacheTolerance: "00:10:00" | ||||
|   # Networks allowed to bypass authentication (loopback by default for on-host cron jobs). | ||||
|   bypassNetworks: | ||||
|     - "127.0.0.1/32" | ||||
|     - "::1/128" | ||||
|  | ||||
| sources: | ||||
|   ghsa: | ||||
|     apiToken: "${GITHUB_PAT}" | ||||
|     pageSize: 50 | ||||
|     maxPagesPerFetch: 5 | ||||
|     requestDelay: "00:00:00.200" | ||||
|     failureBackoff: "00:05:00" | ||||
|     rateLimitWarningThreshold: 500 | ||||
|     secondaryRateLimitBackoff: "00:02:00" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user