@~lyre/auth 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/admin.d.ts CHANGED
@@ -69,12 +69,41 @@ interface InviteResult {
69
69
  userGroupId?: string | null;
70
70
  [key: string]: unknown;
71
71
  }
72
+ /**
73
+ * A profile field an app collects about a user — the spec a consumer renders a form input from.
74
+ * Mirrors Accounts' `fields` registry, so a consumer never hardcodes one app's idea of a person.
75
+ */
76
+ interface ProfileFieldSpec {
77
+ id: string;
78
+ fieldName: string;
79
+ label: string;
80
+ fieldType: string;
81
+ required: boolean;
82
+ hidden: boolean;
83
+ enumValues: string[] | null;
84
+ inputPrefix: string | null;
85
+ validationRegex: string | null;
86
+ validationMessage: string | null;
87
+ displayOrder: number;
88
+ }
89
+ /** Whether an email can be invited to an app. See `checkInviteEmail`. */
90
+ interface InviteEmailCheck {
91
+ email: string;
92
+ /** `member` = already has app access; `invited` = a live invite exists; `available` = go ahead. */
93
+ state: 'member' | 'invited' | 'available';
94
+ /** Whether an Accounts user already exists for this address (they keep their own profile). */
95
+ hasAccount: boolean;
96
+ /** When the pending invite lapses — only for `invited`. */
97
+ expiresAt?: string;
98
+ }
72
99
  /** A pending (not yet accepted, not yet expired) app invitation. */
73
100
  interface PendingInvite {
74
101
  id: string;
75
102
  email: string;
76
103
  /** The workspace the invitee joins on acceptance; null for a group-less invite. */
77
104
  userGroupId: string | null;
105
+ /** Values captured on the invite form, keyed by field name. Prefills the accept form. */
106
+ profileData?: Record<string, string>;
78
107
  createdAt: string;
79
108
  expiresAt: string;
80
109
  /** The inviter's email, when still resolvable. */
@@ -132,11 +161,49 @@ declare class AccountsAdmin {
132
161
  inviteToApp(appSlug: string, input: {
133
162
  email: string;
134
163
  userGroupId?: string | null;
164
+ /** Profile values from the invite form, keyed by field name (see `listAppProfileFields`).
165
+ * Accounts drops any key the app does not collect, so authorization-shaped values
166
+ * (role, assignability) can never be set from here. */
167
+ profileData?: Record<string, string> | null;
135
168
  }): Promise<InviteResult>;
169
+ /**
170
+ * The profile fields this app collects about a user — the spec to render an invite form from.
171
+ * Session-authed. Never includes email: that is the invite's identity, not a profile value.
172
+ */
173
+ listAppProfileFields(appSlug: string): Promise<ProfileFieldSpec[]>;
174
+ /**
175
+ * Whether an email can be invited — for a live check on an invite form, so the inviter learns
176
+ * BEFORE submitting that someone is already a member or already invited. Email only, exact match.
177
+ * Session-authed.
178
+ */
179
+ checkInviteEmail(appSlug: string, email: string): Promise<InviteEmailCheck>;
180
+ /**
181
+ * Add a user to a workspace group. Service-key authed (`users:write`).
182
+ *
183
+ * Membership was read-only over the API, which is why "reactivate user" had to fall back to
184
+ * re-INVITING an existing colleague. Use this to restore membership instead.
185
+ */
186
+ addGroupMember(groupId: string, userId: string, opts?: {
187
+ role?: string;
188
+ }): Promise<void>;
189
+ /**
190
+ * Remove a user from a workspace group. Service-key authed (`users:write`). Idempotent.
191
+ *
192
+ * Removing a user's APP access does NOT remove their group membership, and the members list
193
+ * reads membership — so without this a "deleted" user keeps reappearing in the workspace.
194
+ */
195
+ removeGroupMember(groupId: string, userId: string): Promise<void>;
136
196
  /** Revoke a pending invite (withdraw one sent in error). Session-authed. */
137
197
  revokeAppInvite(appSlug: string, inviteId: string): Promise<void>;
138
198
  /** Everyone with access to an app. Session-authed. */
139
199
  listAppUsers(appSlug: string): Promise<AppMember[]>;
200
+ /**
201
+ * Restore an existing user's access to an app. Session-authed. Idempotent.
202
+ *
203
+ * The counterpart to `removeAppUser`. Distinct from `inviteToApp`: this is for an account that
204
+ * already exists and already consented, so it must NOT put the person through registration again.
205
+ */
206
+ addAppUser(appSlug: string, userId: string): Promise<void>;
140
207
  /** Revoke a user's access to an app. Session-authed. */
141
208
  removeAppUser(appSlug: string, userId: string): Promise<void>;
142
209
  /** Members of a user_group (the workspace's agents). Service-key authed (`stats:read`). */
@@ -203,4 +270,4 @@ declare class AccountsAdmin {
203
270
  /** Convenience factory mirroring the SDK's other `create*` helpers. */
204
271
  declare function createAccountsAdmin(opts: AccountsAdminOptions): AccountsAdmin;
205
272
 
206
- export { AccountsAdmin, AccountsAdminError, type AccountsAdminOptions, type AccountsUser, type AppMember, type ChangePasswordResult, type GroupMember, type InviteResult, type ListUsersQuery, type ListUsersResult, type PendingInvite, createAccountsAdmin };
273
+ export { AccountsAdmin, AccountsAdminError, type AccountsAdminOptions, type AccountsUser, type AppMember, type ChangePasswordResult, type GroupMember, type InviteEmailCheck, type InviteResult, type ListUsersQuery, type ListUsersResult, type PendingInvite, type ProfileFieldSpec, createAccountsAdmin };
package/dist/admin.js CHANGED
@@ -79,6 +79,56 @@ var AccountsAdmin = class {
79
79
  body: input
80
80
  });
81
81
  }
82
+ /**
83
+ * The profile fields this app collects about a user — the spec to render an invite form from.
84
+ * Session-authed. Never includes email: that is the invite's identity, not a profile value.
85
+ */
86
+ async listAppProfileFields(appSlug) {
87
+ const data = await this.request(
88
+ "GET",
89
+ `/api/auth/apps/${encodeURIComponent(appSlug)}/profile-fields`,
90
+ { auth: "session" }
91
+ );
92
+ return data.fields ?? [];
93
+ }
94
+ /**
95
+ * Whether an email can be invited — for a live check on an invite form, so the inviter learns
96
+ * BEFORE submitting that someone is already a member or already invited. Email only, exact match.
97
+ * Session-authed.
98
+ */
99
+ async checkInviteEmail(appSlug, email) {
100
+ return this.request(
101
+ "GET",
102
+ `/api/auth/apps/${encodeURIComponent(appSlug)}/invites/lookup?email=${encodeURIComponent(email)}`,
103
+ { auth: "session" }
104
+ );
105
+ }
106
+ /**
107
+ * Add a user to a workspace group. Service-key authed (`users:write`).
108
+ *
109
+ * Membership was read-only over the API, which is why "reactivate user" had to fall back to
110
+ * re-INVITING an existing colleague. Use this to restore membership instead.
111
+ */
112
+ async addGroupMember(groupId, userId, opts = {}) {
113
+ await this.request(
114
+ "POST",
115
+ `/api/auth/user-groups/${encodeURIComponent(groupId)}/members`,
116
+ { auth: "key", body: { userId, ...opts.role ? { role: opts.role } : {} } }
117
+ );
118
+ }
119
+ /**
120
+ * Remove a user from a workspace group. Service-key authed (`users:write`). Idempotent.
121
+ *
122
+ * Removing a user's APP access does NOT remove their group membership, and the members list
123
+ * reads membership — so without this a "deleted" user keeps reappearing in the workspace.
124
+ */
125
+ async removeGroupMember(groupId, userId) {
126
+ await this.request(
127
+ "DELETE",
128
+ `/api/auth/user-groups/${encodeURIComponent(groupId)}/members?userId=${encodeURIComponent(userId)}`,
129
+ { auth: "key" }
130
+ );
131
+ }
82
132
  /** Revoke a pending invite (withdraw one sent in error). Session-authed. */
83
133
  async revokeAppInvite(appSlug, inviteId) {
84
134
  await this.request(
@@ -96,6 +146,19 @@ var AccountsAdmin = class {
96
146
  );
97
147
  return data.users ?? [];
98
148
  }
149
+ /**
150
+ * Restore an existing user's access to an app. Session-authed. Idempotent.
151
+ *
152
+ * The counterpart to `removeAppUser`. Distinct from `inviteToApp`: this is for an account that
153
+ * already exists and already consented, so it must NOT put the person through registration again.
154
+ */
155
+ async addAppUser(appSlug, userId) {
156
+ await this.request(
157
+ "POST",
158
+ `/api/auth/apps/${encodeURIComponent(appSlug)}/users`,
159
+ { auth: "session", body: { userId } }
160
+ );
161
+ }
99
162
  /** Revoke a user's access to an app. Session-authed. */
100
163
  async removeAppUser(appSlug, userId) {
101
164
  await this.request(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@~lyre/auth",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Shared Axis Accounts auth SDK \u2014 framework-agnostic session/identity core (HMAC-signed cookies, accounts login/callback/logout) plus an optional turnkey SvelteKit adapter.",
5
5
  "type": "module",
6
6
  "sideEffects": false,