Skip to content

Add config.api_authenticate hook for custom API auth#42

Merged
HamptonMakes merged 1 commit intomainfrom
hampton/api-authenticate-hook
Mar 11, 2026
Merged

Add config.api_authenticate hook for custom API auth#42
HamptonMakes merged 1 commit intomainfrom
hampton/api-authenticate-hook

Conversation

@HamptonMakes
Copy link
Collaborator

Problem

The API controllers only support Bearer token authentication. Host apps like coplan-square that have their own auth infrastructure (e.g., Trogdor mTLS) need a way to use it for API calls too — so agents can use sq curl instead of managing separate API tokens.

Solution

Add config.api_authenticate — a hook that follows the same pattern as config.authenticate:

CoPlan.configure do |config|
  config.api_authenticate = ->(request) {
    { external_id: "123", name: "user", admin: false }
  }
end

When set, API controllers use the hook and auto-provision users (same find_or_initialize_by pattern as the web auth). When unset, Bearer token auth remains the default.

Changes

  • Configuration: Added api_authenticate accessor
  • Api::V1::BaseController: New authenticate_api! dispatches to hook or token auth. Added api_actor_id and api_author_type helpers so child controllers don't reference @api_token directly.
  • Child controllers (leases, sessions, comments, operations): Replaced all @api_token.id / ApiToken::HOLDER_TYPE references with the new helpers.

Test results

All 389 specs passing — existing Bearer token tests still pass (hook is nil by default).

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1200c556f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


# The type of actor making the API call (for polymorphic associations).
def api_author_type
@api_token ? ApiToken::HOLDER_TYPE : "CoPlan::User"

Choose a reason for hiding this comment

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

P1 Badge Return valid actor type from api_author_type hook path

When config.api_authenticate is enabled, api_author_type returns "CoPlan::User", but API writes this value into Comment.author_type and PlanVersion.actor_type (comments_controller and operations_controller). Those fields are validated against enum constants that only allow human/local_agent/cloud_persona/system (engine/app/models/coplan/comment.rb and engine/app/models/coplan/plan_version.rb), so hook-authenticated requests will fail to create comments (422) and can fail version commits with RecordInvalid (500), effectively breaking core API editing flows for the new auth mode.

Useful? React with 👍 / 👎.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch! Fixed — api_author_type now returns "human" for hook auth instead of "CoPlan::User". This matches the valid enum values in Comment, PlanVersion, and EditSession.

@HamptonMakes HamptonMakes force-pushed the hampton/api-authenticate-hook branch 2 times, most recently from 34baa4e to 8499fa0 Compare March 11, 2026 16:48
Allows host apps to replace Bearer token authentication with their own
auth mechanism (e.g., Trogdor mTLS at Square). The hook follows the same
pattern as config.authenticate — receives a request, returns user attrs
with :external_id, and auto-provisions users.

When api_authenticate is set, the API controllers use it instead of
Bearer tokens. When unset, Bearer token auth remains the default.

Introduces api_actor_id and api_author_type helpers in BaseController
so child controllers don't reference @api_token directly.

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019cd872-3abe-7556-8927-9966fe044b6c
@HamptonMakes HamptonMakes force-pushed the hampton/api-authenticate-hook branch from 8499fa0 to ff2c348 Compare March 11, 2026 16:53
@HamptonMakes HamptonMakes merged commit 51c7695 into main Mar 11, 2026
2 checks passed
@HamptonMakes HamptonMakes deleted the hampton/api-authenticate-hook branch March 11, 2026 17:55
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.

1 participant