feat: global usernames and rename workspace to default_workspace (#1001)

Users are global entities, not scoped to workspaces. This change:

Track A — Global usernames:
- Change iam_users_by_username to PRIMARY KEY (username), removing
  workspace from the lookup key
- Login looks up username globally, no workspace required
- Username uniqueness is enforced globally, not per-workspace
- Login -w now overrides the JWT workspace (session workspace)
  rather than selecting which user registry to search

Track B — Rename workspace to default_workspace:
- UserRecord.workspace → UserRecord.default_workspace
- Identity.workspace → Identity.default_workspace
- JWT claim "workspace" → "default_workspace"
- IamResponse.resolved_workspace → resolved_default_workspace
- WebSocket auth-ok frame field → default_workspace
- Socket clients read default_workspace from auth-ok
- _user_record_to_dict wire key → default_workspace
- CLI help text and output updated throughout
- Test files updated for renamed fields
This commit is contained in:
cybermaggedon 2026-06-25 16:34:31 +01:00 committed by GitHub
parent 16f8cfd972
commit 0a828379be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 101 additions and 113 deletions

View file

@ -53,7 +53,7 @@ def main():
help="Auth token (default: $TRUSTGRAPH_TOKEN)",
)
parser.add_argument(
"--username", required=True, help="Username (unique in workspace)",
"--username", required=True, help="Username (globally unique)",
)
parser.add_argument(
"--password", default=None,
@ -75,10 +75,7 @@ def main():
)
parser.add_argument(
"-w", "--workspace", default=None,
help=(
"Target workspace (admin only; defaults to caller's "
"assigned workspace)"
),
help="Default workspace for the new user",
)
run_main(do_create_user, parser)

View file

@ -51,8 +51,8 @@ def main():
parser.add_argument(
"-w", "--workspace", default=None,
help=(
"Optional workspace to log in against. Defaults to "
"the user's assigned workspace."
"Override the default workspace for this session's JWT. "
"If omitted, uses the user's stored default workspace."
),
)
run_main(do_login, parser)

View file

@ -68,7 +68,7 @@ def do_update_user(args):
print(f"username : {rec.get('username', '')}")
print(f"name : {rec.get('name', '')}")
print(f"email : {rec.get('email', '')}")
print(f"workspace : {rec.get('workspace', '')}")
print(f"default_ws: {rec.get('default_workspace', '')}")
print(f"roles : {', '.join(rec.get('roles', []))}")
print(f"enabled : {'yes' if rec.get('enabled') else 'no'}")
print(
@ -114,7 +114,7 @@ def main():
"-w", "--workspace", default=None,
help=(
"Optional workspace integrity check — when supplied, "
"iam-svc verifies the target user's home workspace "
"iam-svc verifies the target user's default workspace "
"matches"
),
)