nandorKollar commented on code in PR #3924:
URL: https://github.com/apache/polaris/pull/3924#discussion_r2880687692


##########
site/content/in-dev/unreleased/proposals/observability-rest-api.md:
##########
@@ -0,0 +1,1269 @@
+---
+title: Observability REST API
+linkTitle: Observability REST API
+weight: 100
+---
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+# Proposal: REST API for Querying Table Metrics and Events
+
+**Author:** Anand Sankaran
+**Date:** 2026-03-02
+**Status:** Draft Proposal
+**Target:** Apache Polaris
+
+---
+
+## Abstract
+
+This proposal defines REST API endpoints for querying table metrics and 
catalog events from Apache Polaris. The endpoints expose data already being 
persisted via the existing JDBC persistence model (`events`, 
`scan_metrics_report`, `commit_metrics_report` tables) and follow established 
Polaris API patterns.
+
+**Note:** The Events API in this proposal is designed to align with the 
emerging [Iceberg Events API 
specification](https://github.com/apache/iceberg/pull/12584), which is nearing 
consensus in the Apache Iceberg community. This ensures forward compatibility 
and consistency with the broader Iceberg ecosystem.
+
+---
+
+## Table of Contents
+
+1. [Motivation](#1-motivation)
+2. [Use Cases](#2-use-cases)
+3. [Design Principles](#3-design-principles)
+4. [API Specification](#4-api-specification)
+5. [Authorization](#5-authorization)
+6. [OpenAPI Schema](#6-openapi-schema)
+7. [Implementation Notes](#7-implementation-notes)
+8. [Iceberg Events API Alignment](#8-iceberg-events-api-alignment)
+
+---
+
+## 1. Motivation
+
+Apache Polaris currently persists table metrics (scan reports, commit reports) 
and catalog events to the database, but provides no REST API to query this 
data. Users must access the database directly to retrieve metrics or audit 
information.
+
+Adding read-only REST endpoints enables:
+- Programmatic access to metrics without database credentials
+- Integration with monitoring dashboards and alerting systems
+- Consistent authorization via Polaris RBAC
+- Pagination and filtering without writing SQL
+
+---
+
+## 2. Use Cases
+
+### 2.1 Table Health Monitoring
+- Track write patterns: files added/removed per commit, record counts, 
duration trends
+- Identify tables with high commit frequency or unusually large commits
+- Detect issues indicating need for compaction (many small files) or 
optimization
+
+### 2.2 Query Performance Analysis
+- Understand read patterns: files scanned vs skipped, planning duration
+- Identify inefficient queries with low manifest/file pruning ratios
+- Correlate performance with filter expressions and projected columns
+
+### 2.3 Capacity Planning & Chargeback
+- Aggregate metrics by table, namespace, or principal over time
+- Track storage growth trends (`total_file_size_bytes`)
+- Attribute usage to teams/users via `principal_name`
+
+### 2.4 Debugging & Troubleshooting
+- Correlate metrics with distributed traces (`otel_trace_id`, `otel_span_id`)
+- Investigate specific commits by `snapshot_id`
+- Trace operations via `request_id`
+
+### 2.5 Audit & Compliance
+- Track who created/dropped/modified catalog objects
+- Monitor administrative actions (credential rotation, grant changes)
+- Generate compliance reports for access patterns
+
+---
+
+## 3. Design Principles
+
+| Principle | Rationale |
+|-----------|-----------|
+| **Iceberg Events API alignment** | Events API follows the [Iceberg Events 
API spec](https://github.com/apache/iceberg/pull/12584) for ecosystem 
compatibility |
+| **Dedicated metrics-reports namespace** | Metrics APIs use 
`/api/metrics-reports/v1/...` to separate from management and catalog APIs |
+| **POST for complex filtering** | Events API uses POST with request body (per 
Iceberg spec) to support complex filters (arrays, nested objects) |
+| **Read-only semantics** | All endpoints are read-only; metrics/events are 
written via existing flows |
+| **Consistent pagination** | Follow `continuation-token` pattern (Iceberg) 
and `pageToken` pattern (Polaris APIs) |
+| **Flexible filtering** | Time ranges, operation types, catalog objects - 
common query patterns |
+| **RBAC integration** | Leverage existing Polaris authorization model |
+
+---
+
+## 4. API Specification
+
+### 4.1 Endpoint Summary
+
+| Method | Path | Description |
+|--------|------|-------------|
+| POST | `/api/catalog/v1/{prefix}/events` | Query events for a catalog 
(Iceberg-compatible) |
+| GET | 
`/api/metrics-reports/v1/catalogs/{catalogName}/namespaces/{namespace}/tables/{table}/scan-metrics`
 | List scan metrics for a table |
+| GET | 
`/api/metrics-reports/v1/catalogs/{catalogName}/namespaces/{namespace}/tables/{table}/commit-metrics`
 | List commit metrics for a table |
+
+> **Note:** The Events API uses POST (not GET) and follows the Iceberg REST 
Catalog path structure (`/api/catalog/v1/{prefix}/events`) for compatibility 
with the [Iceberg Events API 
specification](https://github.com/apache/iceberg/pull/12584). The metrics APIs 
use a dedicated `/api/metrics-reports/v1/` namespace since they expose 
pre-populated records rather than managing catalog state - a server that 
doesn't support catalog management may still expose metrics reports.
+
+### 4.2 Path Parameters
+
+| Parameter | Type | Description |
+|-----------|------|-------------|
+| `prefix` | string | Catalog prefix (typically the catalog name) |
+| `catalogName` | string | Name of the catalog |
+| `namespace` | string | Namespace (URL-encoded, multi-level separated by 
`%1F`) |
+| `table` | string | Table name |
+
+### 4.3 Events API (Iceberg-Compatible)
+
+The Events API follows the [Iceberg Events API 
specification](https://github.com/apache/iceberg/pull/12584) for ecosystem 
compatibility. Key design decisions from the Iceberg spec:
+
+- **POST method**: Allows complex filtering with arrays and nested objects in 
the request body
+- **Continuation token**: Opaque cursor for resumable pagination
+- **Operation-centric model**: Events are structured around operations 
(create-table, update-table, etc.)
+- **Custom extensions**: Support for `x-` prefixed custom operation types for 
Polaris-specific events
+
+#### Request Body (`QueryEventsRequest`)
+
+| Property | Type | Required | Description |
+|----------|------|----------|-------------|
+| `continuation-token` | string | No | Opaque cursor to resume fetching from 
previous request |
+| `page-size` | integer | No | Maximum events per page (server may return 
fewer) |
+| `after-timestamp-ms` | long | No | Filter: events after this timestamp 
(inclusive) |
+| `operation-types` | array[string] | No | Filter by operation types (see 
below) |
+| `catalog-objects-by-name` | array[array[string]] | No | Filter by 
namespace/table/view names |
+| `catalog-objects-by-id` | array[object] | No | Filter by table/view UUIDs |
+| `object-types` | array[string] | No | Filter by object type: `namespace`, 
`table`, `view` |
+| `custom-filters` | object | No | Implementation-specific filter extensions |
+
+#### Standard Operation Types
+
+| Operation Type | Description |
+|----------------|-------------|
+| `create-table` | Table created and committed |
+| `register-table` | Existing table registered in catalog |
+| `drop-table` | Table dropped |
+| `update-table` | Table metadata updated |
+| `rename-table` | Table renamed |
+| `create-view` | View created |
+| `drop-view` | View dropped |
+| `update-view` | View updated |
+| `rename-view` | View renamed |
+| `create-namespace` | Namespace created |
+| `update-namespace-properties` | Namespace properties updated |
+| `drop-namespace` | Namespace dropped |
+
+#### Polaris Custom Operation Types
+
+For Polaris-specific events not covered by the Iceberg spec, use the `x-` 
prefix convention:
+
+| Custom Operation Type | Description |
+|----------------------|-------------|
+| `x-polaris-create-catalog-role` | Catalog role created |
+| `x-polaris-grant-privilege` | Privilege granted |
+| `x-polaris-rotate-credentials` | Principal credentials rotated |
+| `x-polaris-create-policy` | Policy created |
+| `x-polaris-attach-policy` | Policy attached to resource |
+
+### 4.4 Query Parameters (Metrics APIs)
+
+#### List Scan Metrics (`/.../tables/{table}/scan-metrics`)
+
+| Parameter | Type | Required | Default | Description |
+|-----------|------|----------|---------|-------------|
+| `pageToken` | string | No | - | Cursor for pagination |
+| `pageSize` | integer | No | 100 | Results per page (max: 1000) |
+| `snapshotId` | long | No | - | Filter by snapshot ID |
+| `principalName` | string | No | - | Filter by principal |
+| `timestampFrom` | long | No | - | Start of time range (epoch ms) |
+| `timestampTo` | long | No | - | End of time range (epoch ms) |
+
+#### List Commit Metrics (`/.../tables/{table}/commit-metrics`)
+
+| Parameter | Type | Required | Default | Description |
+|-----------|------|----------|---------|-------------|
+| `pageToken` | string | No | - | Cursor for pagination |
+| `pageSize` | integer | No | 100 | Results per page (max: 1000) |
+| `snapshotId` | long | No | - | Filter by snapshot ID |
+| `operation` | string | No | - | Filter by operation: `append`, `overwrite`, 
`delete`, `replace` |
+| `principalName` | string | No | - | Filter by principal |
+| `timestampFrom` | long | No | - | Start of time range (epoch ms) |
+| `timestampTo` | long | No | - | End of time range (epoch ms) |
+
+### 4.5 Example Requests and Responses
+
+#### Query Events (Iceberg-Compatible)
+
+**Request:**
+```http
+POST /api/catalog/v1/my-catalog/events
+Authorization: Bearer <token>
+Content-Type: application/json
+
+{
+  "page-size": 2,
+  "operation-types": ["create-table", "update-table"],
+  "after-timestamp-ms": 1709251200000,
+  "catalog-objects-by-name": [
+    ["analytics", "events"]
+  ],
+  "object-types": ["table"]
+}
+```
+
+**Response:**
+```json
+{
+  "next-page-token": "eyJ0cyI6MTcwOTMzNzYxMjM0NSwiaWQiOiI1NTBlODQwMCJ9",
+  "highest-processed-timestamp-ms": 1709337612345,
+  "events": [
+    {
+      "event-id": "550e8400-e29b-41d4-a716-446655440000",
+      "request-id": "req-12345",
+      "request-event-count": 1,
+      "timestamp-ms": 1709337612345,
+      "actor": {
+        "principal": "[email protected]",
+        "client-ip": "192.168.1.100"
+      },
+      "operation": {
+        "operation-type": "create-table",
+        "identifier": {
+          "namespace": ["analytics", "events"],
+          "name": "page_views"
+        },
+        "table-uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+        "updates": [
+          {"action": "assign-uuid", "uuid": 
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},
+          {"action": "set-current-schema", "schema-id": 0},
+          {"action": "set-default-spec", "spec-id": 0}
+        ]
+      }
+    },
+    {
+      "event-id": "661f9511-f30c-52e5-b827-557766551111",
+      "request-id": "req-12346",
+      "request-event-count": 1,
+      "timestamp-ms": 1709337500000,
+      "actor": {
+        "principal": "[email protected]"
+      },
+      "operation": {
+        "operation-type": "update-table",
+        "identifier": {
+          "namespace": ["analytics", "events"],
+          "name": "user_actions"
+        },
+        "table-uuid": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
+        "updates": [
+          {"action": "add-snapshot", "snapshot-id": 123456789}
+        ],
+        "requirements": [
+          {"type": "assert-table-uuid", "uuid": 
"b2c3d4e5-f6a7-8901-bcde-f23456789012"}
+        ]
+      }
+    }
+  ]
+}
+```
+
+#### Query Events with Custom Polaris Operations
+
+**Request:**
+```http
+POST /api/catalog/v1/my-catalog/events
+Authorization: Bearer <token>
+Content-Type: application/json
+
+{
+  "page-size": 10,
+  "operation-types": ["x-polaris-grant-privilege", 
"x-polaris-rotate-credentials"]
+}
+```
+
+**Response:**
+```json
+{
+  "next-page-token": "eyJ0cyI6MTcwOTMzODAwMDAwMH0=",
+  "highest-processed-timestamp-ms": 1709338000000,
+  "events": [
+    {
+      "event-id": "772f0622-g41d-63f6-c938-668877662222",
+      "request-id": "req-admin-001",
+      "request-event-count": 1,
+      "timestamp-ms": 1709338000000,
+      "actor": {
+        "principal": "[email protected]"
+      },
+      "operation": {
+        "operation-type": "custom",
+        "custom-type": "x-polaris-grant-privilege",
+        "identifier": {
+          "namespace": ["analytics", "events"],
+          "name": "page_views"
+        },
+        "table-uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+        "privilege": "TABLE_READ_DATA",
+        "grantee": "data-analyst-role"
+      }
+    }
+  ]
+}
+```
+
+#### List Scan Metrics
+
+**Request:**
+```http
+GET 
/api/metrics-reports/v1/catalogs/my-catalog/namespaces/analytics%1Fevents/tables/page_views/scan-metrics?pageSize=2&timestampFrom=1709251200000
+Authorization: Bearer <token>
+```
+
+**Response:**
+```json
+{
+  "nextPageToken": null,
+  "reports": [
+    {
+      "reportId": "scan-001-abc123",
+      "catalogId": 12345,
+      "tableId": 67890,
+      "timestampMs": 1709337612345,
+      "principalName": "[email protected]",
+      "requestId": "req-scan-001",
+      "otelTraceId": "abc123def456789012345678901234",
+      "otelSpanId": "def456789012",
+      "snapshotId": 1234567890123,
+      "schemaId": 0,
+      "filterExpression": "event_date >= '2024-03-01'",
+      "projectedFieldIds": "1,2,3,5,8",
+      "projectedFieldNames": "event_id,user_id,event_type,timestamp,page_url",
+      "resultDataFiles": 150,
+      "resultDeleteFiles": 5,
+      "totalFileSizeBytes": 1073741824,
+      "totalDataManifests": 12,
+      "totalDeleteManifests": 2,
+      "scannedDataManifests": 8,
+      "scannedDeleteManifests": 2,
+      "skippedDataManifests": 4,
+      "skippedDeleteManifests": 0,
+      "skippedDataFiles": 45,
+      "skippedDeleteFiles": 0,
+      "totalPlanningDurationMs": 250,
+      "equalityDeleteFiles": 3,
+      "positionalDeleteFiles": 2,
+      "indexedDeleteFiles": 0,
+      "totalDeleteFileSizeBytes": 52428800
+    }
+  ]
+}
+```
+
+#### List Commit Metrics
+
+**Request:**
+```http
+GET 
/api/metrics-reports/v1/catalogs/my-catalog/namespaces/analytics%1Fevents/tables/page_views/commit-metrics?operation=append&pageSize=2
+Authorization: Bearer <token>
+```
+
+**Response:**
+```json
+{
+  "nextPageToken": "eyJ0cyI6MTcwOTMzNzcwMDAwMCwiaWQiOiJjb21taXQtMDAyIn0=",
+  "reports": [
+    {
+      "reportId": "commit-001-xyz789",
+      "catalogId": 12345,
+      "tableId": 67890,
+      "timestampMs": 1709337800000,
+      "principalName": "[email protected]",
+      "requestId": "req-commit-001",
+      "otelTraceId": "xyz789abc123456789012345678901",
+      "otelSpanId": "abc123456789",
+      "snapshotId": 1234567890124,
+      "sequenceNumber": 42,
+      "operation": "append",
+      "addedDataFiles": 10,
+      "removedDataFiles": 0,
+      "totalDataFiles": 160,
+      "addedDeleteFiles": 0,
+      "removedDeleteFiles": 0,
+      "totalDeleteFiles": 5,
+      "addedEqualityDeleteFiles": 0,
+      "removedEqualityDeleteFiles": 0,
+      "addedPositionalDeleteFiles": 0,
+      "removedPositionalDeleteFiles": 0,
+      "addedRecords": 100000,
+      "removedRecords": 0,
+      "totalRecords": 15000000,
+      "addedFileSizeBytes": 104857600,
+      "removedFileSizeBytes": 0,
+      "totalFileSizeBytes": 1178599424,
+      "totalDurationMs": 5000,
+      "attempts": 1
+    }
+  ]
+}
+```
+
+---
+
+## 5. Authorization
+
+### 5.1 Required Privileges
+
+This proposal introduces **new dedicated privileges** for reading 
observability data, following the principle of **separation of duties**. This 
ensures that:
+
+- Read-only audit/monitoring access does not require management permissions
+- Monitoring tools can access metrics without requiring data read access
+- Fine-grained access control is possible for different operational roles
+
+| Endpoint | Required Privilege | Scope | New Privilege? |
+|----------|-------------------|-------|----------------|
+| Query Events | `CATALOG_READ_EVENTS` | Catalog | **Yes** |
+| List Scan Metrics | `TABLE_READ_METRICS` | Table | **Yes** |
+| List Commit Metrics | `TABLE_READ_METRICS` | Table | **Yes** |
+
+### 5.2 New Privilege Definitions
+
+| Privilege | Scope | Description |
+|-----------|-------|-------------|
+| `CATALOG_READ_EVENTS` | Catalog | Read-only access to catalog events (audit 
log). Does not grant any management capabilities. |
+| `TABLE_READ_METRICS` | Table | Read-only access to table scan and commit 
metrics. Does not grant access to table data. |
+
+### 5.3 Rationale: Separation of Duties
+
+Introducing dedicated read-only privileges enables proper **separation of 
duties**:
+
+| Use Case | Required Privilege | Why Not Reuse Existing? |
+|----------|-------------------|------------------------|
+| Security auditor reviewing catalog changes | `CATALOG_READ_EVENTS` | Should 
not require `CATALOG_MANAGE_METADATA` (management access) |
+| Monitoring tool collecting table metrics | `TABLE_READ_METRICS` | Should not 
require `TABLE_READ_DATA` (data access) |
+| Data analyst with table access | `TABLE_READ_DATA` implies 
`TABLE_READ_METRICS` | Users who can read data can also see metrics about their 
queries |
+| Catalog admin | `CATALOG_MANAGE_METADATA` implies `CATALOG_READ_EVENTS` | 
Admins can see all events |
+
+### 5.4 Privilege Hierarchy
+
+The new privileges fit into the existing hierarchy as follows:
+
+```
+CATALOG_MANAGE_METADATA
+  └── CATALOG_READ_EVENTS (implied)
+
+TABLE_FULL_METADATA / TABLE_READ_DATA
+  └── TABLE_READ_METRICS (implied)
+```
+
+This means:
+- Users with `CATALOG_MANAGE_METADATA` automatically have `CATALOG_READ_EVENTS`
+- Users with `TABLE_READ_DATA` automatically have `TABLE_READ_METRICS`
+- But the reverse is **not** true: `CATALOG_READ_EVENTS` does not grant 
management access, and `TABLE_READ_METRICS` does not grant data access
+
+### 5.5 Implementation Notes
+
+New privileges require:
+1. Adding entries to `PolarisPrivilege` enum
+2. Updating the privilege hierarchy in the authorizer
+3. Adding privilege checks in the new API endpoints
+
+---
+
+## 6. OpenAPI Schema
+
+> **Note:** The OpenAPI specifications below are embedded in this proposal for 
review context. Upon approval, these should be extracted into separate files 
for ease of processing and proper integration:
+> - **Events API** → `spec/rest-catalog-open-api.yaml` (extending Iceberg REST 
Catalog spec)
+> - **Metrics Reports API** → `spec/metrics-reports-service.yml` (new 
dedicated service spec with base path `/api/metrics-reports/v1/`)
+
+### 6.1 Events API (Iceberg REST Catalog Extension)
+
+Add the following to `spec/rest-catalog-open-api.yaml` (aligned with Iceberg 
Events API spec):
+
+```yaml
+paths:
+  /v1/{prefix}/events:
+    parameters:
+      - $ref: '#/components/parameters/prefix'
+    post:
+      tags:
+        - Catalog API
+      summary: Get events for changes to catalog objects
+      description: >
+        Returns a sequence of changes to catalog objects (tables, namespaces, 
views)
+        that allows clients to efficiently track metadata modifications 
without polling
+        individual resources. Consumers track their progress through a 
continuation-token,
+        enabling resumable synchronization after downtime or errors.
+
+        This endpoint primarily supports use cases like catalog federation, 
workflow
+        triggering, and basic audit capabilities.
+
+        Consumers should be prepared to handle 410 Gone responses when 
requested sequences
+        are outside the server's retention window. Consumers should also 
de-duplicate
+        received events based on the event's `event-id`.
+      operationId: getEvents
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/QueryEventsRequest'
+      responses:
+        '200':
+          description: A sequence of change events to catalog objects
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/QueryEventsResponse'
+        '400':
+          $ref: '#/components/responses/BadRequestErrorResponse'
+        '401':
+          $ref: '#/components/responses/UnauthorizedResponse'
+        '403':
+          $ref: '#/components/responses/ForbiddenResponse'
+        '410':
+          description: Gone - The requested offset is no longer available
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorModel'
+        '503':
+          $ref: '#/components/responses/ServiceUnavailableResponse'
+        '5XX':
+          $ref: '#/components/responses/ServerErrorResponse'
+```
+
+### 6.2 Metrics APIs (New Metrics Reports Service)
+
+Add the following to a new `spec/metrics-reports-service.yml` (or extend 
existing management service):
+
+> **Note:** The metrics APIs use `/api/metrics-reports/v1/` as the base path, 
separate from the management API. This reflects that metrics reports are 
read-only access to pre-populated data, not catalog management operations.
+
+```yaml
+paths:
+  /catalogs/{catalogName}/namespaces/{namespace}/tables/{table}/scan-metrics:
+    parameters:
+      - $ref: '#/components/parameters/catalogName'
+      - $ref: '#/components/parameters/namespace'
+      - $ref: '#/components/parameters/table'
+    get:
+      operationId: listTableScanMetrics
+      summary: List scan metrics for a table
+      tags:
+        - Observability
+      parameters:
+        - name: pageToken
+          in: query
+          schema:
+            type: string
+        - name: pageSize
+          in: query
+          schema:
+            type: integer
+            minimum: 1
+            maximum: 1000
+            default: 100
+        - name: snapshotId
+          in: query
+          schema:
+            type: integer
+            format: int64
+        - name: principalName
+          in: query
+          schema:
+            type: string
+        - name: timestampFrom
+          in: query
+          schema:
+            type: integer
+            format: int64
+        - name: timestampTo
+          in: query
+          schema:
+            type: integer
+            format: int64
+      responses:
+        '200':
+          description: Paginated list of scan metrics
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ListScanMetricsResponse'
+        '403':
+          description: Insufficient privileges
+        '404':
+          description: Table not found
+
+  /catalogs/{catalogName}/namespaces/{namespace}/tables/{table}/commit-metrics:
+    parameters:
+      - $ref: '#/components/parameters/catalogName'
+      - $ref: '#/components/parameters/namespace'
+      - $ref: '#/components/parameters/table'
+    get:
+      operationId: listTableCommitMetrics
+      summary: List commit metrics for a table
+      tags:
+        - Observability
+      parameters:
+        - name: pageToken
+          in: query
+          schema:
+            type: string
+        - name: pageSize
+          in: query
+          schema:
+            type: integer
+            minimum: 1
+            maximum: 1000
+            default: 100
+        - name: snapshotId
+          in: query
+          schema:
+            type: integer
+            format: int64
+        - name: operation
+          in: query
+          schema:
+            type: string
+        - name: principalName
+          in: query
+          schema:
+            type: string
+        - name: timestampFrom
+          in: query
+          schema:
+            type: integer
+            format: int64
+        - name: timestampTo
+          in: query
+          schema:
+            type: integer
+            format: int64
+      responses:
+        '200':
+          description: Paginated list of commit metrics
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ListCommitMetricsResponse'
+        '403':
+          description: Insufficient privileges
+        '404':
+          description: Table not found
+```
+
+### 6.3 Events API Schemas (Iceberg-Compatible)
+
+Add these schemas to `spec/rest-catalog-open-api.yaml`:
+
+```yaml
+components:
+  schemas:
+    QueryEventsRequest:
+      type: object
+      properties:
+        continuation-token:
+          type: string
+          description: >
+            A continuation token to resume fetching events from a previous 
request.
+            If not provided, events are fetched from the beginning of the 
event log
+            subject to other filters.
+        page-size:
+          type: integer
+          format: int32
+          description: >
+            The maximum number of events to return in a single response.
+            Servers may return less results than requested.
+        after-timestamp-ms:
+          type: integer
+          format: int64
+          description: >
+            The timestamp in milliseconds to start consuming events from 
(inclusive).
+        operation-types:
+          type: array
+          items:
+            $ref: "#/components/schemas/OperationType"
+          description: Filter events by operation type.
+        catalog-objects-by-name:
+          type: array
+          items:
+            $ref: "#/components/schemas/CatalogObjectIdentifier"
+          description: >
+            Filter events by catalog objects referenced by name (namespaces, 
tables, views).
+            For namespaces, events for all containing objects are returned 
recursively.
+        catalog-objects-by-id:
+          type: array
+          items:
+            $ref: "#/components/schemas/CatalogObjectUuid"
+          description: Filter events by table/view UUIDs.
+        object-types:
+          type: array
+          items:
+            type: string
+            enum: [namespace, table, view]
+          description: Filter events by catalog object type.
+        custom-filters:
+          type: object
+          additionalProperties: true
+          description: Implementation-specific filter extensions.
+
+    QueryEventsResponse:
+      type: object
+      required:
+        - next-page-token
+        - highest-processed-timestamp-ms
+        - events
+      properties:
+        next-page-token:
+          type: string
+          description: >
+            An opaque continuation token to fetch the next page of events.
+        highest-processed-timestamp-ms:
+          type: integer
+          format: int64
+          description: >
+            The highest event timestamp processed when generating this 
response.
+        events:
+          type: array
+          items:
+            $ref: "#/components/schemas/Event"
+
+    Event:
+      type: object
+      required:
+        - event-id
+        - request-id
+        - request-event-count
+        - timestamp-ms
+        - operation
+      properties:
+        event-id:
+          type: string
+          description: Unique ID of this event. Clients should deduplicate 
based on this ID.
+        request-id:
+          type: string
+          description: >
+            Opaque ID of the request this event belongs to. Events from the 
same
+            request share this ID.
+        request-event-count:
+          type: integer
+          description: >
+            Total number of events generated by this request.
+        timestamp-ms:
+          type: integer
+          format: int64
+          description: Timestamp when this event occurred (epoch milliseconds).
+        actor:
+          type: object
+          additionalProperties: true
+          description: >
+            The actor who performed the operation (e.g., user, service 
account).
+            Content is implementation-specific.
+        operation:
+          type: object
+          description: The operation that was performed.
+          discriminator:
+            propertyName: operation-type
+            mapping:
+              create-table: "#/components/schemas/CreateTableOperation"

Review Comment:
   We should think about how to map Polaris event types (`PolarisEventType` 
enum values) to these operation-types. In Polaris we separate events to before 
and after operation (`BEFORE_CREATE_CATALOG` and `AFTER_CREATE_CATALOG`) how 
can we map these to an `operation-type`? Or they're independent, should we use 
completely separate events here? Probably everything fits in `CustomOperation`, 
but if possible, we should use these standardised event types, though in many 
cases it isn't possible, role and principal related events can only be mapped 
to CustomOperation.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to