Summary
The Harper CLI cannot run add_user / alter_user non-interactively (CI/CD) because it reuses the same username= / password= arguments for both the transport authentication credentials and the operation payload (the user being created/altered). There is no way to authenticate as one user while creating another, short of the interactive harper login prompt.
Reported by Joseph Yoo (CDI, building Harper CI/CD infra-as-code — app-specific users/roles under version control).
Reproduction
# CI wants to auth as an admin and create a new app user:
export HARPER_CLI_USERNAME=admin
export HARPER_CLI_PASSWORD=<admin-pw>
harperdb add_user role=app username=svc_app password=<new-pw> target=https://node:9925
The username=svc_app / password=<new-pw> on the command line are consumed as the auth credentials (they take precedence over the env vars), so the request tries to log in as the user being created and fails.
Root cause
bin/cliOperations.ts:
buildRequest() places every key=value arg directly onto req, so username/password become both payload fields and transport fields.
cliOperations() resolves auth as:
username: req.username || target.username || process.env.HARPER_CLI_USERNAME || process.env.CLI_TARGET_USERNAME,
password: req.password || target.password || process.env.HARPER_CLI_PASSWORD || process.env.CLI_TARGET_PASSWORD,
req.username/req.password (the payload) win over the env-var auth credentials.
- For non-deploy operations the whole
req is sent as the body (body = req), so the payload correctly carries username/password for add_user — but the same values were already (mis)used for auth.
The result: for any operation whose payload legitimately contains username/password (add_user, alter_user), transport auth and operation payload collide, and env-var auth is silently overridden.
Impact
add_user / alter_user are unusable in non-interactive CI/CD pipelines via the CLI.
- The documented env-var auth mechanism (
HARPER_CLI_USERNAME/HARPER_CLI_PASSWORD) is silently overridden by payload params, which is surprising and hard to diagnose.
- Workaround today: bypass the CLI and
curl the operations API directly (Joseph's workaround), or use interactive harper login (not viable for CI/CD).
Proposed direction
Give transport auth its own namespace so it never collides with the operation payload. Options (not mutually exclusive):
- Dedicated auth flags that always win for auth and are never serialized into the body — e.g.
auth_username= / auth_password= (add to TRANSPORT_ONLY_FIELDS). The payload username/password then remain purely the operation fields.
- Make env-var auth authoritative when present — if
HARPER_CLI_USERNAME/HARPER_CLI_PASSWORD are set, prefer them over req.username/req.password for the auth leg (env-var auth is the documented CI path). This is the smaller change but is a precedence flip that needs a compatibility note.
Recommend (1) as the primary, explicit fix (unambiguous, self-documenting for scripts), optionally with (2) as a convenience. Update CLI docs for the CI/CD non-interactive auth story either way.
Acceptance
- Can run
add_user/alter_user non-interactively, authenticating as an existing admin while creating a different user, in a single command with no interactive prompt.
- Auth credentials are never leaked into the operation request body.
- Docs describe the non-interactive CI/CD auth flow.
Summary
The Harper CLI cannot run
add_user/alter_usernon-interactively (CI/CD) because it reuses the sameusername=/password=arguments for both the transport authentication credentials and the operation payload (the user being created/altered). There is no way to authenticate as one user while creating another, short of the interactiveharper loginprompt.Reported by Joseph Yoo (CDI, building Harper CI/CD infra-as-code — app-specific users/roles under version control).
Reproduction
The
username=svc_app/password=<new-pw>on the command line are consumed as the auth credentials (they take precedence over the env vars), so the request tries to log in as the user being created and fails.Root cause
bin/cliOperations.ts:buildRequest()places everykey=valuearg directly ontoreq, sousername/passwordbecome both payload fields and transport fields.cliOperations()resolves auth as:req.username/req.password(the payload) win over the env-var auth credentials.reqis sent as the body (body = req), so the payload correctly carriesusername/passwordforadd_user— but the same values were already (mis)used for auth.The result: for any operation whose payload legitimately contains
username/password(add_user,alter_user), transport auth and operation payload collide, and env-var auth is silently overridden.Impact
add_user/alter_userare unusable in non-interactive CI/CD pipelines via the CLI.HARPER_CLI_USERNAME/HARPER_CLI_PASSWORD) is silently overridden by payload params, which is surprising and hard to diagnose.curlthe operations API directly (Joseph's workaround), or use interactiveharper login(not viable for CI/CD).Proposed direction
Give transport auth its own namespace so it never collides with the operation payload. Options (not mutually exclusive):
auth_username=/auth_password=(add toTRANSPORT_ONLY_FIELDS). The payloadusername/passwordthen remain purely the operation fields.HARPER_CLI_USERNAME/HARPER_CLI_PASSWORDare set, prefer them overreq.username/req.passwordfor the auth leg (env-var auth is the documented CI path). This is the smaller change but is a precedence flip that needs a compatibility note.Recommend (1) as the primary, explicit fix (unambiguous, self-documenting for scripts), optionally with (2) as a convenience. Update CLI docs for the CI/CD non-interactive auth story either way.
Acceptance
add_user/alter_usernon-interactively, authenticating as an existing admin while creating a different user, in a single command with no interactive prompt.