Skip to content

feat(cli): add default machine user to profiles#1419

Merged
toiroakr merged 9 commits into
mainfrom
feat/profile-default-machine-user
Jun 16, 2026
Merged

feat(cli): add default machine user to profiles#1419
toiroakr merged 9 commits into
mainfrom
feat/profile-default-machine-user

Conversation

@dqn

@dqn dqn commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Profiles can now store a default machine user — and optionally lock it — so application-data commands no longer need --machine-user on every invocation. Follow-up to the suggestion in #1147 (comment).

Usage

$ tailor-sdk profile update my-profile --machine-user admin-bot
✔ Profile "my-profile" updated successfully

$ TAILOR_PLATFORM_PROFILE=my-profile tailor-sdk query --engine sql -q 'select * from "User";'
# runs as admin-bot

Resolution order for query, workflow start, function test-run, and machineuser token: command line (--machine-user, or the NAME argument for machineuser token) > TAILOR_PLATFORM_MACHINE_USER_NAME > profile default. function test-run keeps its existing final fallback to the first machine user in tailor.config.ts. Clear the stored default with profile update <name> --machine-user "".

Locking the machine user

--machine-user-override deny turns the default into a fixed value: a differing machine user from the command line or environment fails fast.

$ tailor-sdk profile update my-profile --machine-user viewer-bot --machine-user-override deny

$ TAILOR_PLATFORM_PROFILE=my-profile tailor-sdk query --engine sql --machine-user admin-bot -q '...'
Error [PROFILE_MACHINE_USER_OVERRIDE_DENIED]: Profile "my-profile" denies overriding the machine user.

Like the readonly flag, this is a local guardrail, not a security boundary: it can be lifted with profile update <name> --machine-user-override allow, and paths that bypass profiles (--workspace-id with the current user, direct token use) are governed by the bearer token itself.

Notes

  • Older SDK versions ignore the new machine_user / machine_user_override profile fields and silently drop them when they rewrite the config file (e.g. on token refresh). Re-set them with profile update if older and newer SDK versions share a machine.

dqn added 7 commits June 12, 2026 18:05
Profiles can now store a default machine user name via
`profile create/update --machine-user`. Commands that need a machine
user (query, workflow start, function test-run, machineuser token)
fall back to the active profile's default when neither --machine-user
nor TAILOR_PLATFORM_MACHINE_USER_NAME is provided. Pass an empty
string to `profile update --machine-user ""` to clear the default.
Assert the resolved machine user name (not just success) in test-run
fallback tests, verify option forwarding to loadMachineUserName in
workflow start tests, drop a duplicate profile update test, and add
machineuser token tests for the new optional NAME argument.
The query execution error mapper still read the raw machineUser
option, which is undefined when the name comes from the profile
default or environment variable. Pass the resolved resource name so
error messages always include the machine user.
Bind TAILOR_PLATFORM_MACHINE_USER_NAME to the positional NAME so the
env fallback is declared on the command like the other machine user
commands. Also clarify the changeset wording for machineuser token
(positional NAME, not --machine-user) and rename a resolution
variable in test-run for clarity.
`profile create/update --machine-user-override deny` locks the
profile's machine user: an explicit machine user from the command
line or TAILOR_PLATFORM_MACHINE_USER_NAME that differs from the
stored value fails fast with PROFILE_MACHINE_USER_OVERRIDE_DENIED.
The default (`allow`) keeps the stored value as a fallback only.
Validate the deny/machine-user combination only when a machine-user
flag is part of the update, so a profile left in an inconsistent
state by hand-editing does not block unrelated updates. Key the error
message on the flag that was passed and mention the env var in the
override-denied suggestion.
@changeset-bot

changeset-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 418c285

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@tailor-platform/sdk Minor
@tailor-platform/create-sdk Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jun 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/@tailor-platform/create-sdk@418c285
pnpm add https://pkg.pr.new/@tailor-platform/sdk@418c285

commit: 418c285

@github-actions

This comment has been minimized.

@dqn dqn marked this pull request as ready for review June 12, 2026 14:43
@dqn dqn requested review from a team and toiroakr June 12, 2026 14:43

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📖 Docs Quality & Consistency Check

✅ Docs are consistent with the implementation and contain no user-facing internal-detail leaks.

Checked areas:

  • CLI reference documentation (cli-reference.md) - environment variable descriptions updated to include machineuser token
  • Command documentation (cli/auth.md, cli/function.md, cli/query.md, cli/workflow.md, cli/workspace.md) - all option tables and descriptions accurately reflect the optional nature of --machine-user and the new profile options
  • Machine user resolution priority order (CLI flag > env > profile default) - consistently documented and implemented in loadMachineUserName
  • Error messages across all affected commands - contextually appropriate variations (e.g., machineuser token correctly mentions "NAME positional argument" vs --machine-user for other commands)
  • Profile override deny behavior - implementation matches documented behavior with correct error code PROFILE_MACHINE_USER_OVERRIDE_DENIED
  • Changeset user-facing descriptions - clear and accurate
  • User-facing documentation stays focused on SDK user needs without leaking internal implementation details (no transport, module, or class name references)

Re-run this check by adding the docs-check label to the PR.


…machine-user

# Conflicts:
#	packages/sdk/src/cli/commands/profile/list.ts
@github-actions

This comment has been minimized.

*/
export async function loadMachineUserName(
opts?: LoadMachineUserNameOptions,
): Promise<string | undefined> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With opts?.machineUser || ... || undefined, passing --machine-user "" explicitly to query / workflow start / function test-run / machineuser token makes the empty string falsy and silently falls back to the env var / profile default.

The "empty string = clear" semantics of profile update don't apply here since that path doesn't go through this function — for the consuming commands an empty machine user name is just invalid input. A typo like --machine-user "$UNSET_VAR" would go undetected and run as a different user, so it might be worth rejecting an empty value explicitly:

if (opts?.machineUser === "") {
  throw new Error("Machine user name cannot be empty.");
}

profile update doesn't call loadMachineUserName, so its clear behavior is unaffected.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 418c285. Used a CLIError with code MACHINE_USER_NAME_EMPTY to match the existing PROFILE_MACHINE_USER_OVERRIDE_DENIED path rather than a bare Error.

@toiroakr toiroakr assigned dqn and unassigned toiroakr Jun 15, 2026
An empty --machine-user value silently fell back to the env var or
profile default. Reject it explicitly so a typo like --machine-user
"$UNSET_VAR" surfaces as invalid input instead of running as a
different user.
@github-actions

Copy link
Copy Markdown

Code Metrics Report (packages/sdk)

main (f5dacfb) #1419 (d2b1ea8) +/-
Coverage 67.9% 68.1% +0.2%
Code to Test Ratio 1:0.4 1:0.4 +0.0
Details
  |                    | main (f5dacfb) | #1419 (d2b1ea8) |  +/-  |
  |--------------------|----------------|-----------------|-------|
+ | Coverage           |          67.9% |           68.1% | +0.2% |
  |   Files            |            415 |             415 |     0 |
  |   Lines            |          14572 |           14614 |   +42 |
+ |   Covered          |           9898 |            9962 |   +64 |
+ | Code to Test Ratio |          1:0.4 |           1:0.4 |  +0.0 |
  |   Code             |          96533 |           97338 |  +805 |
+ |   Test             |          42498 |           43147 |  +649 |

Code coverage of files in pull request scope (50.0% → 55.6%)

Files Coverage +/- Status
packages/sdk/src/cli/commands/function/test-run.ts 60.2% +7.0% modified
packages/sdk/src/cli/commands/machineuser/token.ts 76.1% +70.6% modified
packages/sdk/src/cli/commands/profile/create.ts 5.0% -0.6% modified
packages/sdk/src/cli/commands/profile/list.ts 100.0% +30.7% modified
packages/sdk/src/cli/commands/profile/update.ts 88.8% +5.0% modified
packages/sdk/src/cli/commands/workflow/start.ts 28.0% +2.5% modified
packages/sdk/src/cli/query/errors.ts 83.3% +8.3% affected
packages/sdk/src/cli/query/index.ts 51.7% +0.5% modified
packages/sdk/src/cli/shared/context.ts 63.9% +3.7% modified
packages/sdk/src/cli/shared/errors.ts 52.9% +5.8% affected

SDK Configure Bundle Size

main (f5dacfb) #1419 (d2b1ea8) +/-
configure-index-size 19.73KB 19.73KB 0KB
dependency-chunks-size 47.71KB 47.71KB 0KB
total-bundle-size 67.44KB 67.44KB 0KB

Runtime Performance

main (f5dacfb) #1419 (d2b1ea8) +/-
Generate Median 2,686ms 2,912ms 226ms
Generate Max 2,708ms 3,019ms 311ms
Apply Build Median 2,726ms 2,933ms 207ms
Apply Build Max 2,770ms 3,003ms 233ms

Type Performance (instantiations)

main (f5dacfb) #1419 (d2b1ea8) +/-
tailordb-basic 36,061 36,061 0
tailordb-optional 3,841 3,841 0
tailordb-relation 5,921 5,921 0
tailordb-validate 2,566 2,566 0
tailordb-hooks 5,767 5,767 0
tailordb-object 12,136 12,136 0
tailordb-enum 2,462 2,462 0
resolver-basic 9,424 9,424 0
resolver-nested 26,111 26,111 0
resolver-array 18,187 18,187 0
executor-schedule 4,234 4,234 0
executor-webhook 873 873 0
executor-record 6,659 6,659 0
executor-resolver 4,369 4,369 0
executor-operation-function 868 868 0
executor-operation-gql 869 869 0
executor-operation-webhook 888 888 0
executor-operation-workflow 1,714 1,714 0

Reported by octocov

@dqn dqn assigned toiroakr and unassigned dqn Jun 15, 2026

@toiroakr toiroakr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@toiroakr toiroakr merged commit d5bed7c into main Jun 16, 2026
42 checks passed
@toiroakr toiroakr deleted the feat/profile-default-machine-user branch June 16, 2026 00:23
This was referenced Jun 16, 2026
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.

2 participants