From eee746fb4cf0cd2a53db73110afe8c13fd38b818 Mon Sep 17 00:00:00 2001 From: Hubert Chao Date: Tue, 18 Aug 2026 14:43:07 +0000 Subject: [PATCH 1/6] new schemas for CT operator-provided metadata --- log_schema_v4.json | 244 +++++++++++++++++++++++++++++++++++ operator_list_schema_v4.json | 30 +++++ 2 files changed, 274 insertions(+) create mode 100644 log_schema_v4.json create mode 100644 operator_list_schema_v4.json diff --git a/log_schema_v4.json b/log_schema_v4.json new file mode 100644 index 0000000..b76304f --- /dev/null +++ b/log_schema_v4.json @@ -0,0 +1,244 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "id": "https://googlechrome.github.io/CertificateTransparency/log_schema.json", + "title": "CT Log Metadata", + "description": "Detailed metadata for a single Certificate Transparency log, as published by the log operator.", + "type": "object", + "properties": { + "$schema": { + "description": "A URI reference to the schema that this document conforms to.", + "type": "string", + "format": "uri" + }, + "log_id": { + "description": "The SHA-256 hash of the log's public key, base64 encoded.", + "type": "string", + "pattern": "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$", + "minLength": 44, + "maxLength": 44 + }, + "key": { + "description": "The log's public key, base64 encoded (DER-encoded SubjectPublicKeyInfo).", + "type": "string", + "pattern": "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$" + }, + "friendly_name": { + "description": "A brief, human-readable name for the log.", + "type": "string" + }, + "log_spec": { + "description": "The protocol implemented by this log. 'rfc6962' for RFC 6962 logs; 'static-ct-api' for logs implementing the C2SP Static CT API specification.", + "type": "string", + "enum": [ + "rfc6962", + "static-ct-api" + ] + }, + "mmd_seconds": { + "description": "The Maximum Merge Delay in seconds: the maximum time the log promises to incorporate a submitted certificate into the tree.", + "type": "integer", + "minimum": 0 + }, + "intended_use": { + "description": "The operator's declared intended use for this log. 'production' logs are eligible for inclusion in CT programs. 'test' logs are for operator or ecosystem testing and should not be included. 'decommissioned' logs have been permanently shut down by the operator (distinct from 'retired', which is a status that can only be designated by a UA).", + "type": "string", + "enum": [ + "production", + "test", + "decommissioned" + ] + }, + "tls_only": { + "description": "If true, this log only accepts certificates containing the ServerAuth EKU. If false (or absent), the log accepts certificates regardless of EKU.", + "type": "boolean" + }, + "temporal_interval": { + "description": "The window of certificate expiry dates this log accepts.", + "type": "object", + "properties": { + "start_inclusive": { + "type": "string", + "format": "date-time" + }, + "end_exclusive": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "start_inclusive", + "end_exclusive" + ] + }, + "status": { + "description": "The overall operational status of the log as understood by the operator. 'active' \u2014 the log is accepting submissions and serving data. 'readonly' \u2014 submissions are closed but monitoring/tile endpoints remain available (e.g. after a log's temporal window closes). 'inactive' \u2014 all endpoints are offline. This field reflects the operator's intended state, not real-time availability.", + "type": "string", + "enum": [ + "active", + "readonly", + "inactive" + ] + }, + "status_timestamp": { + "description": "The timestamp (ISO 8601) when the current top-level status was last set.", + "type": "string", + "format": "date-time" + }, + "planned_changes": { + "description": "An ordered list of planned future status transitions for this log (e.g. going read-only, then fully inactive). Consumers can use this to prepare for upcoming changes without out-of-band communication.", + "type": "array", + "items": { + "type": "object", + "properties": { + "new_status": { + "description": "The status the log will transition to.", + "type": "string", + "enum": [ + "active", + "readonly", + "inactive" + ] + }, + "effective_date": { + "description": "The date/time (ISO 8601) at which the status change is expected to take effect.", + "type": "string", + "format": "date-time" + }, + "comment": { + "description": "A human-readable explanation of this planned change.", + "type": "string" + } + }, + "required": [ + "new_status", + "effective_date" + ] + } + }, + "final_tree_head": { + "description": "For decommissioned logs: the cryptographically verifiable final state of the log tree, as published by the operator.", + "type": "object", + "properties": { + "sha256_root_hash": { + "type": "string", + "pattern": "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$" + "minLength": 44, + "maxLength": 44 + }, + "tree_size": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "sha256_root_hash", + "tree_size" + ] + }, + "log_software": { + "description": "Optional information about the software powering this log.", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "log_id", + "key", + "friendly_name", + "log_spec", + "mmd_seconds", + "intended_use", + "temporal_interval", + "status", + "status_timestamp" + ], + "if": { + "properties": { + "log_spec": { + "const": "rfc6962" + } + } + }, + "then": { + "properties": { + "endpoint": { + "$ref": "#/definitions/EndpointInfo" + } + }, + "required": [ + "endpoint" + ] + }, + "else": { + "properties": { + "submission_endpoint": { + "$ref": "#/definitions/EndpointInfo" + }, + "monitoring_endpoint": { + "$ref": "#/definitions/EndpointInfo" + } + }, + "required": [ + "submission_endpoint", + "monitoring_endpoint" + ] + }, + "definitions": { + "EndpointInfo": { + "description": "URL and optional rate limit information for a single log endpoint. Operational status is expressed at the top-level log object, not per endpoint.", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri" + }, + "rate_limit": { + "description": "Optional rate limit information for this endpoint.", + "type": "object", + "properties": { + "requests": { + "description": "Maximum number of requests permitted within the interval.", + "type": "integer", + "minimum": 0 + }, + "interval_seconds": { + "description": "The time window in seconds over which the request count applies.", + "type": "integer", + "minimum": 1 + }, + "scope": { + "description": "The dimension against which this rate limit is applied.", + "type": "string", + "enum": [ + "ip", + "asn", + "subnet", + "user-agent", + "geography", + "global" + ] + } + }, + "required": [ + "requests", + "interval_seconds" + ] + } + }, + "required": [ + "url" + ] + } + } +} + diff --git a/operator_list_schema_v4.json b/operator_list_schema_v4.json new file mode 100644 index 0000000..a80870e --- /dev/null +++ b/operator_list_schema_v4.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "id": "https://googlechrome.github.io/CertificateTransparency/operator_list_schema.json", + "title": "CT Log Operator List", + "description": "A lightweight manifest published by a CT Log Operator, listing the metadata URLs for each log (or log family) they operate. CT Programs consume this file to discover individual log metadata without requiring out-of-band communication.", + "type": "object", + "properties": { + "$schema": { + "description": "A URI reference to the schema that this document conforms to.", + "type": "string", + "format": "uri" + }, + "operator_name": { + "description": "The human-readable name of the CT Log Operator.", + "type": "string" + }, + "logs": { + "description": "An array of URLs, each pointing to the log-metadata.json file for a log (or log family) operated by this operator. This list only needs to change when a new log is added.", + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + } + }, + "required": [ + "operator_name", + "logs" + ] +} From 8472433e0821dacf6157f2ac04a2ba99d2ee1d58 Mon Sep 17 00:00:00 2001 From: Hubert Chao Date: Tue, 18 Aug 2026 14:56:52 +0000 Subject: [PATCH 2/6] updated URL --- log_schema_v4.json | 2 +- operator_list_schema_v4.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/log_schema_v4.json b/log_schema_v4.json index b76304f..3ddbf2c 100644 --- a/log_schema_v4.json +++ b/log_schema_v4.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "id": "https://googlechrome.github.io/CertificateTransparency/log_schema.json", + "id": "https://googlechrome.github.io/CertificateTransparency/log_schema_v4.json", "title": "CT Log Metadata", "description": "Detailed metadata for a single Certificate Transparency log, as published by the log operator.", "type": "object", diff --git a/operator_list_schema_v4.json b/operator_list_schema_v4.json index a80870e..6a8daa3 100644 --- a/operator_list_schema_v4.json +++ b/operator_list_schema_v4.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "id": "https://googlechrome.github.io/CertificateTransparency/operator_list_schema.json", + "id": "https://googlechrome.github.io/CertificateTransparency/operator_list_schema_v4.json", "title": "CT Log Operator List", "description": "A lightweight manifest published by a CT Log Operator, listing the metadata URLs for each log (or log family) they operate. CT Programs consume this file to discover individual log metadata without requiring out-of-band communication.", "type": "object", From 64dcd55630894f0f7c0457bbe44c180df22b4b36 Mon Sep 17 00:00:00 2001 From: Hubert Chao Date: Wed, 19 Aug 2026 23:11:56 +0000 Subject: [PATCH 3/6] rename files --- log_schema_v4.json => log_schema_v2.json | 0 operator_list_schema_v4.json => operator_list_schema_v1.json | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename log_schema_v4.json => log_schema_v2.json (100%) rename operator_list_schema_v4.json => operator_list_schema_v1.json (100%) diff --git a/log_schema_v4.json b/log_schema_v2.json similarity index 100% rename from log_schema_v4.json rename to log_schema_v2.json diff --git a/operator_list_schema_v4.json b/operator_list_schema_v1.json similarity index 100% rename from operator_list_schema_v4.json rename to operator_list_schema_v1.json From 404ca803cb84d59f16fb2b164f73213b5a0d3661 Mon Sep 17 00:00:00 2001 From: Hubert Chao Date: Wed, 19 Aug 2026 23:35:46 +0000 Subject: [PATCH 4/6] match ID up with file name --- log_schema_v2.json | 2 +- operator_list_schema_v1.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/log_schema_v2.json b/log_schema_v2.json index 3ddbf2c..b91f9bd 100644 --- a/log_schema_v2.json +++ b/log_schema_v2.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "id": "https://googlechrome.github.io/CertificateTransparency/log_schema_v4.json", + "id": "https://googlechrome.github.io/CertificateTransparency/log_schema_v2.json", "title": "CT Log Metadata", "description": "Detailed metadata for a single Certificate Transparency log, as published by the log operator.", "type": "object", diff --git a/operator_list_schema_v1.json b/operator_list_schema_v1.json index 6a8daa3..b73e1a2 100644 --- a/operator_list_schema_v1.json +++ b/operator_list_schema_v1.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "id": "https://googlechrome.github.io/CertificateTransparency/operator_list_schema_v4.json", + "id": "https://googlechrome.github.io/CertificateTransparency/operator_list_schema_v1.json", "title": "CT Log Operator List", "description": "A lightweight manifest published by a CT Log Operator, listing the metadata URLs for each log (or log family) they operate. CT Programs consume this file to discover individual log metadata without requiring out-of-band communication.", "type": "object", From 02d93c593d08e1273b7a810da44d26761c6be741 Mon Sep 17 00:00:00 2001 From: Hubert Chao Date: Mon, 24 Aug 2026 15:23:25 +0000 Subject: [PATCH 5/6] remove rate limiting stanzas --- log_schema_v2.json | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/log_schema_v2.json b/log_schema_v2.json index b91f9bd..237d21c 100644 --- a/log_schema_v2.json +++ b/log_schema_v2.json @@ -195,44 +195,12 @@ }, "definitions": { "EndpointInfo": { - "description": "URL and optional rate limit information for a single log endpoint. Operational status is expressed at the top-level log object, not per endpoint.", + "description": "URL for a single log endpoint. Operational status is expressed at the top-level log object, not per endpoint.", "type": "object", "properties": { "url": { "type": "string", "format": "uri" - }, - "rate_limit": { - "description": "Optional rate limit information for this endpoint.", - "type": "object", - "properties": { - "requests": { - "description": "Maximum number of requests permitted within the interval.", - "type": "integer", - "minimum": 0 - }, - "interval_seconds": { - "description": "The time window in seconds over which the request count applies.", - "type": "integer", - "minimum": 1 - }, - "scope": { - "description": "The dimension against which this rate limit is applied.", - "type": "string", - "enum": [ - "ip", - "asn", - "subnet", - "user-agent", - "geography", - "global" - ] - } - }, - "required": [ - "requests", - "interval_seconds" - ] } }, "required": [ From 4728e4878082c9e75f6272c1e08d8074e347e74f Mon Sep 17 00:00:00 2001 From: Hubert Chao Date: Mon, 24 Aug 2026 15:28:36 +0000 Subject: [PATCH 6/6] add missing comma --- log_schema_v2.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log_schema_v2.json b/log_schema_v2.json index 237d21c..a734012 100644 --- a/log_schema_v2.json +++ b/log_schema_v2.json @@ -121,7 +121,7 @@ "properties": { "sha256_root_hash": { "type": "string", - "pattern": "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$" + "pattern": "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$", "minLength": 44, "maxLength": 44 },