Skip to content

feat: add JSON API for FDO Owner Server with OpenAPI specification - #130

Draft
djach7 wants to merge 11 commits into
fido-device-onboard:mainfrom
djach7:owner-api-refactor
Draft

feat: add JSON API for FDO Owner Server with OpenAPI specification#130
djach7 wants to merge 11 commits into
fido-device-onboard:mainfrom
djach7:owner-api-refactor

Conversation

@djach7

@djach7 djach7 commented Nov 21, 2025

Copy link
Copy Markdown
Collaborator

This pull request adds a JSON API for the FDO Owner Server that returns structured JSON documents while maintaining full backward compatibility with existing PEM-based clients.

Changes

  • OpenAPI 3.0.3 Specification - Complete API specification with type-safe Go code generation
  • oapi-codegen Migration - Moved from npm-based openapi-generator to Go-native oapi-codegen v2.5.1
  • JSON Response System - All endpoints return structured JSON with proper content negotiation
  • Error Handling Consolidation - Centralized error patterns across API handlers
  • Content-Type Enforcement - Strict PEM upload validation per OpenAPI specification
  • Go Generate Workflow - Proper tool dependency management and code generation pipeline
  • Production Optimization - Eliminated debugging artifacts and fixed code smells
  • Shared Component Structure - Organized OpenAPI specs for future manufacturer/rendezvous servers

API Endpoints Enhanced

  • /health - Server health status with version information (JSON)
  • /api/v1/ownerinfo - Owner redirect configuration management (JSON)
  • /api/v1/owner/vouchers - Ownership voucher operations (JSON)

New Files

  • api/openapi/owner-server.yaml - OpenAPI 3.0.3 specification
  • api/openapi/generated.go - Generated Go types and server interfaces
  • api/openapi/config.yaml - oapi-codegen configuration
  • api/openapi/generate.go - go:generate implementation
  • api/openapi/README.md - Code generation documentation
  • api/openapi/shared/ - Shared components for future server specs
  • api/handlers/responses.go - JSON response utilities and error handling
  • api/handlersTest/json_api_test.go - JSON API validation tests
  • api/handlersTest/helpers_test.go - Test helper functions

Modified Files

  • api/handlers/vouchers.go - JSON responses and simplified PEM handling
  • api/handlers/health.go - JSON health endpoint implementation
  • api/handlers/ownerinfo.go - JSON owner redirect API with error consolidation
  • api/handlers/rvinfo.go - Consistent error handling patterns
  • api/handlersTest/vouchers_test.go - Content-type validation tests
  • api/routes.go - Updated imports for generated types
  • scripts/fdo-utils.sh - Optimized utility functions for JSON API
  • Makefile - go generate workflow and tool management
  • go.mod / go.sum - oapi-codegen dependencies
  • .gitignore - Generated file handling

@djach7
djach7 force-pushed the owner-api-refactor branch 3 times, most recently from dfb5a39 to 12406f4 Compare November 21, 2025 19:30
@djach7
djach7 marked this pull request as ready for review November 25, 2025 14:49

@mmartinv mmartinv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I think this is a good step forward to having an implementation we need more refinement and agree on the tools we are going to use and how to split the APIs, e.g.: the health api is going to be use by all the servers and we don't need 3 different implementations, the same will happen with the device CA cert management)

Comment thread api/handlers/vouchers.go Outdated
Comment thread Makefile Outdated
@djach7
djach7 force-pushed the owner-api-refactor branch 5 times, most recently from 730470d to ede9b40 Compare December 3, 2025 20:48
Comment thread api/handlers/health.go Outdated
Comment thread api/handlersTest/health_test.go
Comment thread Makefile Outdated
Comment thread api/handlers/vouchers.go Outdated
Comment thread api/handlers/responses.go Outdated
Comment thread api/handlers/responses.go Outdated
Comment thread api/handlers/vouchers.go Outdated
Comment thread api/handlers/vouchers.go Outdated

@kgiusti kgiusti left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple 'o questions: First, why doesn't the patch use the generated ServerInterface/Handler code? Seems like we're not leveraging a big chunk of the generated functionality. When I look at the server examples on the oapi-codegen website it appears that we only need to provide the ServiceInterface impl and the Http server setup code.

Second, what's the reason the patch uses the chi server as opposed to the go-native (or other server options)? Not implying it's wrong or anything - I'm not familiar with these other server impls - just interested in the motivation for choosing chi. Thanks

@djach7
djach7 force-pushed the owner-api-refactor branch from ede9b40 to b25df8d Compare December 5, 2025 16:24
Comment thread api/handlers/rvinfo.go Fixed
Comment thread api/handlers/vouchers.go Fixed
Comment thread api/handlers/vouchers.go Fixed
@djach7
djach7 force-pushed the owner-api-refactor branch from b25df8d to 1b3e00f Compare December 5, 2025 16:34
@djach7

djach7 commented Dec 5, 2025

Copy link
Copy Markdown
Collaborator Author

@kgiusti Thanks for reviewing! I just pushed an update that hopefully addresses all of your comments. In response to your direct questions:

  1. You're right, and this latest update should utilize the generated code more effectively. It does, however, create some issues with the CI and interacting with the manufacturing server since it hasn't been refactored yet. I added in some temporary backwards compatibility wrappers, although judging by the CI failures I don't think they're working. I'll try to figure that out, the CI passes for me locally.
  2. The chi choice wasn't based in any hard opinions, it was based on Claude being adamant that chi implements http.Handler and mounts easily under ServeMux, while staying close to native Go patterns. If there's another server that would be preferred I'm not against giving it a shot.

@djach7
djach7 force-pushed the owner-api-refactor branch 3 times, most recently from f5a914b to 458f37d Compare December 8, 2025 14:01
Comment thread cmd/owner.go Fixed
@djach7
djach7 force-pushed the owner-api-refactor branch 3 times, most recently from 69a7b42 to d248805 Compare December 8, 2025 18:51
@djach7
djach7 force-pushed the owner-api-refactor branch 2 times, most recently from 58490ef to da6bad2 Compare December 11, 2025 18:00
Comment thread api/openapi/owner-server.yaml Outdated
Comment thread api/openapi/owner-server.yaml Outdated
Comment thread api/openapi/README.md Outdated
Comment thread cmd/owner.go Outdated
Comment thread Makefile Outdated
Comment thread Makefile Outdated
Comment thread api/handlers/rvinfo.go Outdated
Comment thread api/openapi/generate.go Outdated
@djach7
djach7 force-pushed the owner-api-refactor branch from fc7cef6 to 42b2c72 Compare December 12, 2025 16:55
Comment thread api/handlers/rvinfo.go Outdated
Comment thread api/handlers/ownerinfo.go Outdated
Comment thread api/handlers/responses.go Outdated
@djach7

djach7 commented Dec 17, 2025

Copy link
Copy Markdown
Collaborator Author

@kgiusti Just pushed up a change related to what we talked about on Monday. The ownerinfo endpoint should be completely gone, and there's some JSON unmarshaling happening now as well. The JSON stuff isn't fully where I'd like it to be, right now it just does some unmarshaling for validation and then remarshals it to send it to UpdateOwnerInfo. I felt like changing the database function was outside the scope of this PR, but if it isn't I can take a look at that too. I could also be totally missing something (or forgetting something from our conversation), in which case I apologize.

@djach7
djach7 marked this pull request as draft January 8, 2026 14:43
@djach7
djach7 force-pushed the owner-api-refactor branch 2 times, most recently from e5d6cae to e08b7f4 Compare January 12, 2026 18:36

@mmartinv mmartinv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many things to review and to modify, I just reviewed and commented a few.

I think we should lower the scope of this PR to a single API to simplify things and make faster iterations.

Why don't we just restrict this PR to the rvto2addr.yaml API which is the most simple API (the health API is already implemented in #156 in a better way)?

Once we have that we can start with voucher.yaml after merging resell.yaml into it.

What do you think?

Comment thread api/health.yaml
summary: Health check
operationId: getHealth
responses:
'200':

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The the API returns 200 only? How do we know when it fails?

Comment thread api/health.yaml
properties:
status:
type: string
enum: ["healthy"]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This returns always "healthy" which doesn't seem to be right. I think it would help if we also add a "message" to help with the troubleshooting. Please see https://github.com/fido-device-onboard/go-fdo-server/pull/156/changes#diff-fd178fe5d04fd5b4e01530fa592af9681aafb6fdb64d09cba9c950e5f68e8088R30

Comment thread api/resell.yaml
required: true
schema:
type: string
pattern: '^[a-fA-F0-9]{32}$'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should allow uppercase letters in the GUID, lowercase and numbers are enough. The same for other occurrences

Comment thread api/components.yaml
Comment on lines +27 to +67
VoucherInsertResponse:
type: object
required:
- processed
- inserted
properties:
processed:
type: integer
description: Number of vouchers processed
inserted:
type: integer
description: Number of vouchers successfully inserted

VoucherResponse:
type: object
required:
- voucher
- encoding
properties:
voucher:
type: string
description: Base64 encoded voucher data
encoding:
type: string
enum: ["pem"]
description: Voucher encoding format

RVTO2Addr:
type: object
required:
- rvto2addr
properties:
rvto2addr:
type: array
items:
type: array
items:
oneOf:
- type: integer
- type: string
description: Rendezvous TO2 address information No newline at end of file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are specific types, the should go in the respective APIs, please see #156

Comment thread api/resell.yaml
description: Voucher resell endpoints

paths:
/owner/resell/{guid}:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be part of the voucher API (/vouchers/{guid}/extend). I don't really like the "resell" word for this: the API is going to be used by the Owner and the also by the Manufacturer and the Manufacturer is not "reselling" but "selling" for the first time. As both the Manufacturer and Owner can shell their devices, the way I would think about this is, independently if I am an Owner or a Manufacturer: If I own the device I can sell it by extending the voucher.

Comment thread api/components.yaml
Comment on lines +54 to +66
RVTO2Addr:
type: object
required:
- rvto2addr
properties:
rvto2addr:
type: array
items:
type: array
items:
oneOf:
- type: integer
- type: string

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread api/rvto2addr.yaml
description: Rendezvous TO2 address management endpoints

paths:
/owner/redirect:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/owner/redirect:
/rvto2addr:

Comment thread api/rvto2addr.yaml
paths:
/owner/redirect:
get:
summary: Get owner redirect information

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said in previous comments: If you are going to rename Owner Info,
I think Rendezvous TO2 Address or even Device on-boarding address/URL is more accurate than Owner Redirect Info.

I am wondering why are you defining the rvto2addr.yaml API from scratch in this way when there's something already done at https://github.com/fido-device-onboard/go-fdo-server/pull/154/changes#diff-2e7681f1cfb4420391185bff11a9619926890b4b81b8558b59ac964c251e5628R16

Comment thread internal/db/state.go
return sqlDB.Close()
}

// FetchRvInfoJSON reads the rvinfo JSON from the database

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are mixing things here: RVInfo is not part of the owner API.

@@ -0,0 +1,9 @@
package: health
output: handlers/health/gen.go
generate:

@mmartinv mmartinv Jan 13, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add std-http-server: true to the generate: in all the configurations (except the one for components)

djach7 added 11 commits January 13, 2026 08:58
  This pull request adds a JSON API for the FDO Owner Server that returns structured JSON documents while maintaining full
  backward compatibility with existing PEM-based clients.

  Changes

  - OpenAPI 3.0.3 Specification - Complete API specification with type-safe Go code generation
  - JSON Response System - All endpoints return structured JSON with proper content negotiation
  - Error Handling Consolidation - Centralized error patterns across API handlers
  - Content-Type Enforcement - Strict PEM upload validation per OpenAPI specification
  - Go Generate Workflow - Proper tool dependency management and code generation pipeline
  - Production Optimization - Eliminated debugging artifacts and fixed code smells
  - Shared Component Structure - Organized OpenAPI specs for future manufacturer/rendezvous servers

  API Endpoints Enhanced

  - /health - Server health status with version information (JSON)
  - /api/v1/ownerinfo - Owner redirect configuration management (JSON)
  - /api/v1/owner/vouchers - Ownership voucher operations (JSON)

  New Files

  - api/openapi/owner-server.yaml - OpenAPI 3.0.3 specification
  - api/openapi/generated.go - Generated Go types and server interfaces
  - api/openapi/config.yaml - oapi-codegen configuration
  - api/openapi/generate.go - go:generate implementation
  - api/openapi/README.md - Code generation documentation
  - api/openapi/shared/ - Shared components for future server specs
  - api/handlers/responses.go - JSON response utilities and error handling
  - api/handlersTest/json_api_test.go - JSON API validation tests
  - api/handlersTest/helpers_test.go - Test helper functions

  Modified Files

  - api/handlers/vouchers.go - JSON responses and simplified PEM handling
  - api/handlers/health.go - JSON health endpoint implementation
  - api/handlers/ownerinfo.go - JSON owner redirect API with error consolidation
  - api/handlers/rvinfo.go - Consistent error handling patterns
  - api/handlersTest/vouchers_test.go - Content-type validation tests
  - api/routes.go - Updated imports for generated types
  - scripts/fdo-utils.sh - Optimized utility functions for JSON API
  - Makefile - go generate workflow and tool management
  - go.mod / go.sum - oapi-codegen dependencies
  - .gitignore - Generated file handling

Signed-off-by: djach7 <djachimo@redhat.com>
…handlers

Signed-off-by: djach7 <djachimo@redhat.com>
…erate

Signed-off-by: djach7 <djachimo@redhat.com>
…s between server definitions

Signed-off-by: djach7 <djachimo@redhat.com>
…uplication in owner spec

Signed-off-by: djach7 <djachimo@redhat.com>
Signed-off-by: djach7 <djachimo@redhat.com>
Signed-off-by: djach7 <djachimo@redhat.com>
…h Miguel's suggestions

Signed-off-by: djach7 <djachimo@redhat.com>
Signed-off-by: djach7 <djachimo@redhat.com>
Signed-off-by: djach7 <djachimo@redhat.com>
@djach7
djach7 force-pushed the owner-api-refactor branch from e08b7f4 to 039cd93 Compare January 13, 2026 14:10
}

func (s *Server) handleGetVouchers(w http.ResponseWriter, r *http.Request) {
// TODO: Implement voucher listing logic

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants