taldir

Directory service to resolve wallet mailboxes by messenger addresses
Log | Files | Refs | Submodules | README | LICENSE

commit 8ea7d55f56548cb5e3c652fb1f435b8efbccd0ea
parent d83bbf9909cc30409e1eff12006c420f3a5ee714
Author: Yannick Rehberger <yr@ityreh.de>
Date:   Tue, 21 Apr 2026 19:09:25 +0200

add openapi spec

Diffstat:
M.gitignore | 1+
MMakefile.in | 5++++-
MREADME.md | 66++++++++++++++++++++++++++++++++++++++----------------------------
Mcmd/taldir-server/main.go | 6++++++
Mpkg/taldir/taldir.go | 50++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 99 insertions(+), 29 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,2 +1,3 @@ .gitignore **/validation_code +swagger.json diff --git a/Makefile.in b/Makefile.in @@ -59,4 +59,7 @@ gana: dist: git archive --format=tar.gz -o taler-directory-${GITVER}.tar.gz --prefix=taler-directory-${GITVER}/ HEAD -.PHONY: all gana server tools check format uninstall install dist +openapi: + swag init -g main.go --dir ./cmd/taldir-server,./pkg/taldir --outputTypes json --output . -v3.1 + +.PHONY: all gana server tools check format uninstall install dist openapi diff --git a/README.md b/README.md @@ -33,35 +33,35 @@ The following configuration variables exist: For the `[taldir]` section: - * "production" (boolean): true for a production deployment. Causes verbose log messages to be inhibited. - * "db_backend" (string): "sqlite" for the SQLite database backend to be used. - * "validators" (array): An array of strings for the validators/identity types that can be used. Currently supported values: "email" - * "email_sender" (string): For email validations, what should the sender address be. - * "host" (string): For the validation link, which hostname should be used (useful if behind proxy). - * "bind_to" (string): Where to bind and listen (HTTP server). - * "salt" (string): The salt to use for identity key hashes in the database may alternatively be an environment variable `TALDIR_SALT`. - * "monthly_fee" (string): The monthly fee for a registration (Default: "KUDOS:1") - * "default_doc_filetype" (string): The default file type for the terms of service and privacy policy documents (Default: "text/markdown") - * "default_doc_lang" (string): The default language for the terms of service and privacy policy documents (Default: "en-US") - * "default_tos_path" (string): The path for the terms of service documents. Taldir will look for `<lang>.<extension>` depending on the requested file type ("Accept"-header) and locale ("Accept-Language"-header) (Default: "terms/") - * "default_pp_path" (string): See `default_tos_path` (Default: "privacy/") - * "challenge_bytes" (number): The number of bytes (entropy) of the generated challenge (Default: 16) - * "validation_initiation_max" (number): How many challenges can be requested to validate an address (Default: 3) - * "validation_timeframe" (string): The timeframe in which challenges can be requested up to `validation_initiation_max` times (Default: 10m) - * "solution_attempt_max" (number): How often can the solution be attempted for a challenge in the `solution_attempt_timeframe` (Default: 3) - * "solution_attempt_timeframe" (string): The timeframe in which the solution can be attempted `solution_attempt_max` times (Default: "1h") - * "merchant_baseurl_privat" (string): The base URL for the merchant API to use (Default: "http://merchant.taldir/instances/myInstance") - * "merchant_token" (string): The access token for the merchant API (Default: "superSecretToken") - * "validation_landing" (string): The location of the HTML template to use for the validation landing displaying a QR code. (Default: "templates/validation_landing.html" - * "validation_expiration" (string): The duration for which incomplete registration requests are kept. (Default: "24h") +- "production" (boolean): true for a production deployment. Causes verbose log messages to be inhibited. +- "db_backend" (string): "sqlite" for the SQLite database backend to be used. +- "validators" (array): An array of strings for the validators/identity types that can be used. Currently supported values: "email" +- "email_sender" (string): For email validations, what should the sender address be. +- "host" (string): For the validation link, which hostname should be used (useful if behind proxy). +- "bind_to" (string): Where to bind and listen (HTTP server). +- "salt" (string): The salt to use for identity key hashes in the database may alternatively be an environment variable `TALDIR_SALT`. +- "monthly_fee" (string): The monthly fee for a registration (Default: "KUDOS:1") +- "default_doc_filetype" (string): The default file type for the terms of service and privacy policy documents (Default: "text/markdown") +- "default_doc_lang" (string): The default language for the terms of service and privacy policy documents (Default: "en-US") +- "default_tos_path" (string): The path for the terms of service documents. Taldir will look for `<lang>.<extension>` depending on the requested file type ("Accept"-header) and locale ("Accept-Language"-header) (Default: "terms/") +- "default_pp_path" (string): See `default_tos_path` (Default: "privacy/") +- "challenge_bytes" (number): The number of bytes (entropy) of the generated challenge (Default: 16) +- "validation_initiation_max" (number): How many challenges can be requested to validate an address (Default: 3) +- "validation_timeframe" (string): The timeframe in which challenges can be requested up to `validation_initiation_max` times (Default: 10m) +- "solution_attempt_max" (number): How often can the solution be attempted for a challenge in the `solution_attempt_timeframe` (Default: 3) +- "solution_attempt_timeframe" (string): The timeframe in which the solution can be attempted `solution_attempt_max` times (Default: "1h") +- "merchant_baseurl_privat" (string): The base URL for the merchant API to use (Default: "http://merchant.taldir/instances/myInstance") +- "merchant_token" (string): The access token for the merchant API (Default: "superSecretToken") +- "validation_landing" (string): The location of the HTML template to use for the validation landing displaying a QR code. (Default: "templates/validation_landing.html" +- "validation_expiration" (string): The duration for which incomplete registration requests are kept. (Default: "24h") For the `[taldir-pq]` section: - * "host" (string): The host of the Postgres database to use (Default: "localhost") - * "port" (number): The port of the Postres database to use (Default: 5432) - * "user" (string): The database user (Default: "taldir") - * "password" (string): The database user password (Default: "secret") - * "db_name" (string): The database name (Default: "taldir") +- "host" (string): The host of the Postgres database to use (Default: "localhost") +- "port" (number): The port of the Postres database to use (Default: 5432) +- "user" (string): The database user (Default: "taldir") +- "password" (string): The database user password (Default: "secret") +- "db_name" (string): The database name (Default: "taldir") Examples and defaults for the configuration can be found in the `taldir.conf` file shipped with this software. @@ -112,8 +112,8 @@ in the `taldir` section in the Taldir configuration file. Further, a `taldir-<name>` section must exists which contains the following variables: - * "challenge_fee" (amount): The cost of a single challenge using this validation method. - * "command" (string): The program to use to trigger the out of band transfer of the validation code. +- "challenge_fee" (amount): The cost of a single challenge using this validation method. +- "command" (string): The program to use to trigger the out of band transfer of the validation code. ## Validator command @@ -147,6 +147,16 @@ $ cp -r contrib/tos/en terms/ $ cp -r contrib/pp/en terms/ ``` +# Generate OpenAPI Spec + +You can generate an openapi spec from code to `./swagger.json`: + +``` +$ go install github.com/swaggo/swag/v2/cmd/swag@latest +$ ./configure --prefix=PREFIX +$ make openapi +``` + # Funding This project is funded through [NGI TALER Fund](https://nlnet.nl/taler), a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu) program. Learn more at the [NLnet project page](https://nlnet.nl/project/TALER-LookupService). diff --git a/cmd/taldir-server/main.go b/cmd/taldir-server/main.go @@ -16,6 +16,12 @@ // // SPDX-License-Identifier: AGPL3.0-or-later +// @title Taler Directory API +// @description The Taler Directory (TalDir) maps alias hashes to wallet URIs. Clients register an alias by completing an out-of-band challenge, then look it up later using the hashed alias. +// @contact.url https://taler.net +// @license.name AGPL-3.0-or-later +// @license.url https://www.gnu.org/licenses/agpl-3.0.html +// @BasePath / package main /* TODO diff --git a/pkg/taldir/taldir.go b/pkg/taldir/taldir.go @@ -250,6 +250,15 @@ func (t *Taldir) isPMSValid(pms string) (err error) { // Primary lookup function. // Allows the caller to query a wallet key using the hash(!) of the // alias +// +// @Summary Look up an alias entry +// @Description Returns the target URI associated with the given hashed alias. +// @Tags entries +// @Produce json +// @Param h_alias path string true "Crockford base32-encoded SHA-512 hash of the alias" +// @Success 200 {object} Entry +// @Failure 404 +// @Router /{h_alias} [get] func (t *Taldir) getSingleEntry(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var entry Entry @@ -320,6 +329,20 @@ func saltHAlias(hAlias string, salt string) string { // Called by the registrant to validate the registration request. The reference ID was // provided "out of band" using a validation method such as email or SMS +// +// @Summary Complete alias registration +// @Description Submits the solution to the out-of-band challenge to confirm the registration. +// @Tags registration +// @Accept json +// @Param h_alias path string true "Crockford base32-encoded SHA-512 hash of the alias" +// @Param body body ValidationConfirmation true "Challenge solution" +// @Success 204 "Registration confirmed" +// @Failure 400 {object} ErrorDetail "Invalid JSON" +// @Failure 403 "Wrong solution" +// @Failure 404 "Validation not found" +// @Failure 429 "Too many solution attempts" +// @Failure 500 +// @Router /{h_alias} [post] func (t *Taldir) validationRequest(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var entry Entry @@ -426,6 +449,25 @@ func (t *Taldir) isRateLimited(hAlias string) (bool, error) { return false, nil } +// registerRequest initiates the registration or update of an alias. +// +// @Summary Initiate alias registration +// @Description Starts the registration process for an alias. Sends an out-of-band challenge +// @Description via the specified validator (e.g. email or SMS). If the entry already exists +// @Description with no changes, returns the remaining validity instead. +// @Tags registration +// @Accept json +// @Produce json +// @Param alias_type path string true "Alias type (e.g. \"email\", \"sms\")" +// @Param body body RegisterMessage true "Registration request" +// @Success 200 {object} object{valid_for=integer} "Existing entry unchanged; returns remaining validity in microseconds" +// @Success 202 "Challenge sent" +// @Failure 400 {object} ErrorDetail "Invalid request body or target URI" +// @Failure 402 "Payment required" +// @Failure 404 {object} ErrorDetail "Alias type not supported" +// @Failure 429 {object} RateLimitedResponse "Registration rate limit reached" +// @Failure 500 +// @Router /register/{alias_type} [post] func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var req RegisterMessage @@ -631,6 +673,14 @@ func (t *Taldir) oidcValidatorResponse(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) } +// configResponse returns the service configuration. +// +// @Summary Get service configuration +// @Description Returns service metadata including the supported alias types and monthly fee. +// @Tags config +// @Produce json +// @Success 200 {object} VersionResponse +// @Router /config [get] func (t *Taldir) configResponse(w http.ResponseWriter, r *http.Request) { meths := []AliasType{} i := 0