{"id":29675732,"url":"https://github.com/oxidecomputer/v-api","last_synced_at":"2026-04-23T00:02:32.834Z","repository":{"id":231132552,"uuid":"758562034","full_name":"oxidecomputer/v-api","owner":"oxidecomputer","description":"Very small API","archived":false,"fork":false,"pushed_at":"2026-04-15T19:55:17.000Z","size":1033,"stargazers_count":8,"open_issues_count":21,"forks_count":5,"subscribers_count":17,"default_branch":"main","last_synced_at":"2026-04-15T21:33:37.006Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oxidecomputer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-02-16T15:32:51.000Z","updated_at":"2026-04-15T19:52:17.000Z","dependencies_parsed_at":"2024-06-02T04:27:22.555Z","dependency_job_id":"44c22c0f-c10d-424e-8507-78bffe039d35","html_url":"https://github.com/oxidecomputer/v-api","commit_stats":null,"previous_names":["oxidecomputer/v-api"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/oxidecomputer/v-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fv-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fv-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fv-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fv-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oxidecomputer","download_url":"https://codeload.github.com/oxidecomputer/v-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fv-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32159964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T17:06:48.269Z","status":"ssl_error","status_checked_at":"2026-04-22T17:06:19.037Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-22T23:38:15.638Z","updated_at":"2026-04-23T00:02:32.826Z","avatar_url":"https://github.com/oxidecomputer.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# v-api (very small API)\n\nBoilerplate for building an API on top of [dropshot](https://github.com/oxidecomputer/dropshot).\n\n### Why?\n\nWriting user and access code can be tedious. It would be nice if you could inject a batch of\nroutes in to an existing [dropshot](https://github.com/oxidecomputer/dropshot) server and get an\nAPI for handling users and access groups out.\n\n### Integration\n\nThe crate assumes that the hosting application is using a Postgres database or can provide a\nconnection to one. Want a different backend? Please contribute, it will be gladly welcome.\n\nThe `v-model` crate contains [diesel](https://diesel.rs/) migrations for initializing the necessary\ntables in a database. `v-model-installer` exposes embedded migrations via [diesel_migrations](https://docs.rs/diesel_migrations/latest/diesel_migrations/).\n\nTo add the endpoints in to the hosting server:\n\n1. Derive the `v_api` permission traits for your Permission enum. You can use the built-in macro:\n\n```rust\nuse v_api::permissions::VPermission;\nuse v_api_permission_derive::v_api;\n\n#[v_api(From(VPermision))]\npub enum MyPermission {\n  // ...\n}\n```\n\nOr implement the `VAppPermission` trait yourself:\n\n```rust\npub trait VAppPermission: Permission + From\u003cVPermission\u003e + AsScope + PermissionStorage {}\n```\n\n2. Implement the `ApiContext` trait for your server context. This trait is how you communicate to\n`v-api` where your `VContext` struct can be located.\n\n```rust\nimpl ApiContext for MyContext {\n    type AppPermissions = MyPermission;\n    fn v_ctx(\u0026self) -\u003e \u0026VContext\u003cSelf::AppPermissions\u003e {\n        \u0026self.v_context\n    }\n}\n```\n\n3. Use the injection macros to register the `v-api` endpoints. Note that these must both be used\nwithin the same file.\n\n```rust\nuse v_api::{inject_endpoints, v_system_endpoints};\n\nlet context = MyContext::new();\nv_system_endpoints!(context);\n\n/// ...\n\nlet mut api = ApiDescription::new().tag_config(/** ... **/);\ninject_endpoints!(api);\n```\n\n### Endpoints\n\nThe following endpoints are injected by the `inject_endpoints` macro:\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | /oauth/client | Vliew all OAuth clients |\n| POST | /oauth/client | Create a new OAuth client |\n| GET | /oauth/client/{client_id} | View an individual OAuth client |\n| POST | /oauth/client/{client_id}/secret | Create a new secret for an OAuth client |\n| DELETE | /oauth/client/{client_id}/secret/{secret_id} | Delete an existing secret from an OAuth client |\n| POST | /oauth/client/{client_id}/redirect_uri | Add a redirect URI to an OAuth cleint |\n| DELETE | /oauth/client/{client_id}/redirect_uri/{redirect_uri_id} | Delete an existing redirect URI from an OAuth client |\n| GET | /login/oauth/{provider}/code/authorize | Start an OAuth authorization_code flow |\n| GET | /login/oauth/{provider}/code/callback | Internal url for handling return calls from external OAuth providers |\n| POST | /login/oauth/{provider}/code/token | Complete an authorization_code flow by exchanging an authorization code for an access token |\n| GET | /login/oauth/{provider}/device | Start an OAuth device_code flow |\n| POST | /login/oauth/{provider}/device/exchange | Complete a device_code flow by exchanging a request for an access token |\n| GET | /.well-known/openid-configuration | Retrive OpenID configuartion information. Specifically the jwks url |\n| GET | /.well-known/jwks.json | Retrieve JWKS for verifying access tokens |\n| GET | /self | View information about the calling user |\n| GET | /api-user/{identifier} | View information about a specific user |\n| POST | /api-user | Create a new user |\n| POST | /api-user/{identifier} | Update information on an existing user |\n| GET | /api-user/{identifier}/token | View all API tokens for an existing user |\n| POST | /api-user/{identifier}/token | Create a new API token for an existing user |\n| GET | /api-user/{identifier}/token/{token_identifier} | View an existing API token |\n| DELETE | /api-user/{identifier}/token/{token_identifier} | Delete an existing API token |\n| POST | /api-user/{identifier}/group | Add an existing user to a group |\n| DELETE | /api-user/{identifier}/group/{group_id} | Remove an existing user from a group |\n| POST | /api-user/{identifier}/link | TBD |\n| POST | /api-user-provider/{identifier}/link-token | TBD |\n| GET | /group | View all groups |\n| POST | /group | Create a new group |\n| PUT | /group/{group_id} | Update an existing group |\n| DELETE | /group/{group_id} | Delete an existing group |\n| GET | /mapper | View all mappers |\n| POST | /mapper | Create a new mapper |\n| DELETE | /mapper/{identifier} | Delete and existing mapper |\n\n## Contributing\n\nWe're open to PRs that improve these services, especially if they make the repo easier for others\nto use and contribute to. However, we are a small company, and the primary goal of this repo is as\nan internal tool for Oxide, so we can't guarantee that PRs will be integrated.\n\n## License\n\nUnless otherwise noted, all components are licensed under the\n[Mozilla Public License Version 2.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidecomputer%2Fv-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foxidecomputer%2Fv-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidecomputer%2Fv-api/lists"}