Skip to content

Commit 227a8c9

Browse files
authored
Basic API key for mutations (#33)
1 parent f439520 commit 227a8c9

File tree

26 files changed

+981
-355
lines changed

26 files changed

+981
-355
lines changed

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ anyhow = "1.0"
1818
async-trait = "0.1"
1919
axum = { version = "0.8", features = ["macros", "multipart"] }
2020
axum-extra = { version = "0.9", features = ["cookie"] }
21+
base64 = "0.22"
2122
bytes = "1.9"
2223
chrono = { version = "0.4", features = ["serde"] }
2324
clap = { version = "4.5", features = ["derive"] }
2425
futures = "0.3"
26+
hmac = "0.12"
2527
log = "0.4"
28+
rand = "0.8"
29+
sha2 = "0.10"
2630
minijinja = { version = "2.12", features = ["loader"] }
2731
minijinja-autoreload = "2.12.0"
2832
minijinja-embed = "2.12.0"
@@ -53,4 +57,5 @@ tracing = "0.1"
5357
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
5458
utoipa = { version = "5", features = ["axum_extras", "chrono", "uuid"] }
5559
utoipa-swagger-ui = { version = "9", features = ["axum"] }
56-
uuid = { version = "1.11", features = ["v4", "v7", "serde", "js"] }
60+
uuid = { version = "1.11", features = ["v4", "v7", "serde", "js"] }
61+
utoipa-axum = { version = "0.2"}

crates/observation-tools-client/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ log.workspace = true
1616
napi = { version = "3", features = ["async", "tokio_rt", "anyhow"] }
1717
napi-derive = { version = "3", features = ["type-def"] }
1818
observation-tools-macros.workspace = true
19-
observation-tools-shared.workspace = true
19+
observation-tools-shared = { workspace = true, features = ["testing"] }
2020
progenitor-client.workspace = true
2121
reqwest = { workspace = true, features = ["json"] }
2222
serde.workspace = true
@@ -38,6 +38,8 @@ utoipa.workspace = true
3838
[dev-dependencies]
3939
anyhow.workspace = true
4040
observation-tools-server.workspace = true
41+
rand.workspace = true
42+
reqwest.workspace = true
4143
tempfile = { workspace = true }
4244
test-log.workspace = true
4345
tracing-subscriber.workspace = true

crates/observation-tools-client/build.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
use observation_tools_server::api::ApiDoc;
21
use progenitor::GenerationSettings;
32
use progenitor::InterfaceStyle;
43
use syn::__private::quote::quote;
5-
use utoipa::OpenApi;
64

75
fn main() {
86
napi_build::setup();
97

108
// Generate OpenAPI spec from server code
11-
let openapi = ApiDoc::openapi();
9+
let (_, _, openapi) = observation_tools_server::api::build_api();
1210
let mut spec = serde_json::to_value(&openapi).expect("Failed to serialize OpenAPI spec");
1311

1412
// Convert OpenAPI 3.1 to 3.0 for progenitor compatibility

crates/observation-tools-client/index.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
/** Client for observation-tools */
44
export declare class Client {
55
beginExecution(name: string): ExecutionHandle
6+
/**
7+
* Begin a new execution with a specific ID (for testing)
8+
*
9+
* This allows tests to create an execution with a known ID, enabling
10+
* navigation to the execution URL before the execution is uploaded.
11+
*/
12+
beginExecutionWithId(id: string, name: string): ExecutionHandle
613
}
714

815
/** Builder for Client */
@@ -11,6 +18,8 @@ export declare class ClientBuilder {
1118
constructor()
1219
/** Set the base URL for the server */
1320
setBaseUrl(url: string): void
21+
/** Set the API key for authentication */
22+
setApiKey(apiKey: string): void
1423
/** Build the client */
1524
build(): Client
1625
}
@@ -34,3 +43,11 @@ export declare class ExecutionHandle {
3443
*/
3544
observe(name: string, payloadJson: string, labels?: Array<string> | undefined | null, sourceFile?: string | undefined | null, sourceLine?: number | undefined | null, metadata?: Array<Array<string>> | undefined | null): string
3645
}
46+
47+
/**
48+
* Generate a new execution ID (for testing)
49+
*
50+
* This allows tests to generate an execution ID before creating the execution,
51+
* enabling navigation to the execution URL before the execution is uploaded.
52+
*/
53+
export declare function generateExecutionId(): string

crates/observation-tools-client/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,3 +575,4 @@ module.exports = nativeBinding
575575
module.exports.Client = nativeBinding.Client
576576
module.exports.ClientBuilder = nativeBinding.ClientBuilder
577577
module.exports.ExecutionHandle = nativeBinding.ExecutionHandle
578+
module.exports.generateExecutionId = nativeBinding.generateExecutionId

crates/observation-tools-client/openapi.json

Lines changed: 11 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,6 @@
3838
"description": "Response after creating observations",
3939
"type": "object"
4040
},
41-
"ErrorResponse": {
42-
"description": "API error response",
43-
"properties": {
44-
"code": {
45-
"description": "Optional error code",
46-
"nullable": true,
47-
"type": "string"
48-
},
49-
"details": {
50-
"description": "Optional additional details"
51-
},
52-
"error": {
53-
"description": "Error message",
54-
"type": "string"
55-
}
56-
},
57-
"required": [
58-
"error"
59-
],
60-
"type": "object"
61-
},
6241
"Execution": {
6342
"description": "An execution represents the root scope for data collection.\nAll observations are associated with one execution.",
6443
"properties": {
@@ -130,29 +109,6 @@
130109
],
131110
"type": "object"
132111
},
133-
"ListExecutionsQuery": {
134-
"description": "Query parameters for listing executions",
135-
"properties": {
136-
"limit": {
137-
"description": "Maximum number of results to return",
138-
"minimum": 0,
139-
"nullable": true,
140-
"type": "integer"
141-
},
142-
"offset": {
143-
"description": "Number of results to skip (for pagination)",
144-
"minimum": 0,
145-
"nullable": true,
146-
"type": "integer"
147-
},
148-
"search": {
149-
"description": "Search query for execution names or metadata",
150-
"nullable": true,
151-
"type": "string"
152-
}
153-
},
154-
"type": "object"
155-
},
156112
"ListExecutionsResponse": {
157113
"description": "Response for listing executions",
158114
"properties": {
@@ -174,44 +130,6 @@
174130
],
175131
"type": "object"
176132
},
177-
"ListObservationsQuery": {
178-
"description": "Query parameters for listing observations",
179-
"properties": {
180-
"labels": {
181-
"description": "Filter by labels (comma-separated)",
182-
"nullable": true,
183-
"type": "string"
184-
},
185-
"limit": {
186-
"description": "Maximum number of results to return",
187-
"minimum": 0,
188-
"nullable": true,
189-
"type": "integer"
190-
},
191-
"offset": {
192-
"description": "Number of results to skip (for pagination)",
193-
"minimum": 0,
194-
"nullable": true,
195-
"type": "integer"
196-
},
197-
"parent_span_id": {
198-
"description": "Filter by parent span ID",
199-
"nullable": true,
200-
"type": "string"
201-
},
202-
"search": {
203-
"description": "Search query for observation names or metadata",
204-
"nullable": true,
205-
"type": "string"
206-
},
207-
"source_file": {
208-
"description": "Filter by source file",
209-
"nullable": true,
210-
"type": "string"
211-
}
212-
},
213-
"type": "object"
214-
},
215133
"ListObservationsResponse": {
216134
"description": "Response for listing observations",
217135
"properties": {
@@ -350,16 +268,19 @@
350268
],
351269
"type": "object"
352270
}
271+
},
272+
"securitySchemes": {
273+
"bearer_auth": {
274+
"bearerFormat": "API Key",
275+
"description": "API key authentication. Set OBSERVATION_TOOLS_API_SECRET on the server to enable.",
276+
"scheme": "bearer",
277+
"type": "http"
278+
}
353279
}
354280
},
355281
"info": {
356-
"description": "API for the Observation Tools developer data inspection toolkit",
357-
"license": {
358-
"identifier": "AGPL-3",
359-
"name": "AGPL-3"
360-
},
361-
"title": "Observation Tools API",
362-
"version": "0.1.0"
282+
"title": "",
283+
"version": ""
363284
},
364285
"openapi": "3.0.3",
365286
"paths": {
@@ -388,16 +309,6 @@
388309
"nullable": true,
389310
"type": "integer"
390311
}
391-
},
392-
{
393-
"description": "Search query for execution names or metadata",
394-
"in": "query",
395-
"name": "search",
396-
"required": false,
397-
"schema": {
398-
"nullable": true,
399-
"type": "string"
400-
}
401312
}
402313
],
403314
"responses": {
@@ -487,46 +398,6 @@
487398
"nullable": true,
488399
"type": "integer"
489400
}
490-
},
491-
{
492-
"description": "Search query for observation names or metadata",
493-
"in": "query",
494-
"name": "search",
495-
"required": false,
496-
"schema": {
497-
"nullable": true,
498-
"type": "string"
499-
}
500-
},
501-
{
502-
"description": "Filter by labels (comma-separated)",
503-
"in": "query",
504-
"name": "labels",
505-
"required": false,
506-
"schema": {
507-
"nullable": true,
508-
"type": "string"
509-
}
510-
},
511-
{
512-
"description": "Filter by source file",
513-
"in": "query",
514-
"name": "source_file",
515-
"required": false,
516-
"schema": {
517-
"nullable": true,
518-
"type": "string"
519-
}
520-
},
521-
{
522-
"description": "Filter by parent span ID",
523-
"in": "query",
524-
"name": "parent_span_id",
525-
"required": false,
526-
"schema": {
527-
"nullable": true,
528-
"type": "string"
529-
}
530401
}
531402
],
532403
"responses": {
@@ -730,15 +601,5 @@
730601
]
731602
}
732603
}
733-
},
734-
"tags": [
735-
{
736-
"description": "Execution management endpoints",
737-
"name": "executions"
738-
},
739-
{
740-
"description": "Observation management endpoints",
741-
"name": "observations"
742-
}
743-
]
604+
}
744605
}

0 commit comments

Comments
 (0)