@hanzo/rooms 0.1.85 → 0.1.87
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/Chat.js +1 -1
- package/dist/Orgs.js +15 -25
- package/dist/lib/session.d.ts +12 -4
- package/dist/lib/session.js +40 -8
- package/package.json +1 -1
package/dist/Chat.js
CHANGED
|
@@ -1529,7 +1529,7 @@ function Thread({ placeholder = message(), initial, anonymous = false, heading,
|
|
|
1529
1529
|
// with it when it did. `Ask` passes its own, because the page embedding
|
|
1530
1530
|
// it already has an `<h1>` and a second is the defect that took the
|
|
1531
1531
|
// landings off /chat and /dev.
|
|
1532
|
-
empty: heading === null ? undefined : (_jsxs(YStack, { "data-slot": "opening", items: "center", width: "100%", pt: "$6", pb: "$2", ...(media.sm ? null : { flex: 1, justify: "
|
|
1532
|
+
empty: heading === null ? undefined : (_jsxs(YStack, { "data-slot": "opening", items: "center", width: "100%", pt: "$6", pb: "$2", ...(media.sm ? null : { flex: 1, justify: "flex-end" }), children: [room.length > 1 ? (_jsx(XStack, { items: "center", justify: "center", mb: "$4", children: room.map((name, i) => (_jsx(Box, { ml: i ? -16 : 0, rounded: 40, borderWidth: 2, borderColor: "$background", z: room.length - i, children: _jsx(Face, { src: faces[name]?.avatar, emoji: faces[name]?.emoji, name: name, size: 72 }) }, name))) })) : portrait ? (_jsx(Box, { width: 160, height: 160, rounded: 24, overflow: "hidden", borderWidth: 2, borderColor: "var(--white-15)", boxShadow: "0 10px 24px color-mix(in srgb, var(--pure-black) 70%, transparent)", mb: "$4", bg: "var(--neutral-900)", children: _jsx(View, { render: _jsx("img", { src: portrait, alt: withWhom }), width: "100%", height: "100%", objectFit: "cover" }) })) : null, room.length === 1 && !portrait ? (_jsx(Box, { mb: "$3", children: _jsx(Face, { emoji: mate?.emoji ?? persona?.emoji, name: withWhom, size: 72 }) })) : null, _jsx(Text, { render: "h1", fontSize: "$7", lineHeight: "$7", fontWeight: "700", color: "$ink", text: "center", mb: "$1", children: join(room) || heading || (firstName ? `What’s up, ${firstName}?` : "What’s up?") }), room.length === 1 && (mate?.description ?? persona?.description) ? (_jsx(Text, { fontSize: "$3", color: "$soft", text: "center", maxW: 500, mb: "$4", lineHeight: "$4", children: mate?.description ?? persona?.description })) : null] })),
|
|
1533
1533
|
// The transcript reads at the same measure. `Thread` defaults to 768
|
|
1534
1534
|
// itself; handing it the column here is what lets Width reach it.
|
|
1535
1535
|
column: { maxW: MEASURE }, composer: prompt({ ...composing, field: mention.field }, mention.state) }), _jsx(AgentMaker, {}), carry.dialog, _jsx(XStack, { items: "center", justify: "center", py: "$1", px: "$3", gap: "$2", children: isFree(model) ? (_jsxs(Text, { fontSize: "$1", color: "$soft", children: ["Free chat is data-shared to train models.", " ", _jsx(Anchor, { href: site("/legal/privacy"), fontSize: "$1", color: "$ink", children: "Privacy" })] })) : (_jsxs(_Fragment, { children: [_jsx(Anchor, { href: site("/legal/terms"), fontSize: "$1", color: "$soft", children: "Terms" }), _jsx(Text, { fontSize: "$1", color: "$soft", children: "\u00B7" }), _jsx(Anchor, { href: site("/legal/privacy"), fontSize: "$1", color: "$soft", children: "Privacy" })] })) }), consent, _jsx(Upgrade, { ask: ask, onClose: () => setAsk(null) })] }));
|
package/dist/Orgs.js
CHANGED
|
@@ -47,7 +47,8 @@ import { matches, refusal, slugify } from './lib/orgname.js';
|
|
|
47
47
|
import { team as workspace } from './lib/host.js';
|
|
48
48
|
import { checkoutUrl, money } from './lib/pay.js';
|
|
49
49
|
import { cartUrl, charge, priced, usePlan, usePlans } from './lib/plans.js';
|
|
50
|
-
import { createInvitation, inviteLink } from './lib/invite.js';
|
|
50
|
+
import { createInvitation, inviteLink, setOrganizationProfile } from './lib/invite.js';
|
|
51
|
+
import { createOrg, say } from './lib/org.js';
|
|
51
52
|
import { countSignup } from './lib/intent.js';
|
|
52
53
|
import { BAD, mix } from './lib/mix.js';
|
|
53
54
|
import { useRooms } from './host.js';
|
|
@@ -647,12 +648,15 @@ function Everyone({ q, skip }) {
|
|
|
647
648
|
*
|
|
648
649
|
* The slug follows the name the way IAM's onboarding makes it, until it is typed
|
|
649
650
|
* over; a slug typed is IAM's to take as it is, so one IAM would not keep is
|
|
650
|
-
* refused here with the rule, never rewritten.
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*
|
|
651
|
+
* refused here with the rule, never rewritten. The create is the one every
|
|
652
|
+
* surface uses, `POST /v1/account/orgs` (lib/org.ts `createOrg`): it files the
|
|
653
|
+
* organization in IAM and records the reader as its owner through IAM's
|
|
654
|
+
* membership API, the account untouched. IAM's own `/v1/iam/onboard` is not
|
|
655
|
+
* reachable from here: the edge answers no app origin's CORS on it, because it
|
|
656
|
+
* re-keys the session (cloud cors_origin.go `sessionRoutes`). It is sent the
|
|
657
|
+
* name when the name makes the slug, and the slug when the slug was typed, the
|
|
658
|
+
* display name then written on the row (lib/invite.ts `setOrganizationProfile`).
|
|
659
|
+
* The token in hand predates it, so it is refreshed before the organization opens.
|
|
656
660
|
*/
|
|
657
661
|
function Found({ onClose, onMade }) {
|
|
658
662
|
const { sdk } = useIam();
|
|
@@ -681,29 +685,15 @@ function Found({ onClose, onMade }) {
|
|
|
681
685
|
return setRefused(wrong);
|
|
682
686
|
setBusy(true);
|
|
683
687
|
setRefused(null);
|
|
684
|
-
const headers = { Authorization: `Bearer ${bearer() ?? ''}`, 'Content-Type': 'application/json' };
|
|
685
|
-
const why = async (r) => {
|
|
686
|
-
const body = (await r.json().catch(() => null));
|
|
687
|
-
return body?.error || body?.detail || body?.msg || body?.message || `IAM answered ${r.status}.`;
|
|
688
|
-
};
|
|
689
688
|
try {
|
|
690
689
|
const named = slugify(display) === slug;
|
|
691
|
-
const
|
|
692
|
-
if (!r.ok)
|
|
693
|
-
throw new Error(await why(r));
|
|
694
|
-
const made = (await r.json().catch(() => null))?.org;
|
|
695
|
-
if (!made)
|
|
696
|
-
throw new Error('IAM made no organization. Try again.');
|
|
690
|
+
const made = await createOrg(named ? display : slug);
|
|
697
691
|
renew();
|
|
698
692
|
await sdk.refreshAccessToken().catch(() => null);
|
|
699
693
|
if (!named) {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
headers: { ...headers, Authorization: `Bearer ${bearer() ?? ''}` },
|
|
703
|
-
body: JSON.stringify({ owner: 'admin', name: made, displayName: display }),
|
|
694
|
+
await setOrganizationProfile('admin', made, { displayName: display }).catch((err) => {
|
|
695
|
+
throw new Error(`${made} is made, and it is still called ${made}: ${say(err)}`);
|
|
704
696
|
});
|
|
705
|
-
if (!p.ok)
|
|
706
|
-
throw new Error(`${made} is made, and it is still called ${made}: ${await why(p)}`);
|
|
707
697
|
}
|
|
708
698
|
// A token that does not carry it yet is minted on the next load, which opens it.
|
|
709
699
|
if (!claimed().includes(made)) {
|
|
@@ -714,7 +704,7 @@ function Found({ onClose, onMade }) {
|
|
|
714
704
|
onMade(made);
|
|
715
705
|
}
|
|
716
706
|
catch (err) {
|
|
717
|
-
setRefused(err
|
|
707
|
+
setRefused(say(err));
|
|
718
708
|
setBusy(false);
|
|
719
709
|
}
|
|
720
710
|
};
|
package/dist/lib/session.d.ts
CHANGED
|
@@ -129,10 +129,18 @@ export declare function follow(was: string | undefined, moved: () => void): () =
|
|
|
129
129
|
*/
|
|
130
130
|
export declare const DIRECTORIES: readonly string[];
|
|
131
131
|
/**
|
|
132
|
-
* The
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
132
|
+
* The orgs the platform runs under its own names (hanzoai/authz claims.go
|
|
133
|
+
* `platformOrgs`): the brands and the estate's own namespaces. One is a tenant
|
|
134
|
+
* only of the people who run it, its owners and admins, and of a SuperAdmin; a
|
|
135
|
+
* customer who landed in a brand org as a plain member belongs to none of its
|
|
136
|
+
* data, and cloud refuses every request scoped to it.
|
|
137
|
+
*/
|
|
138
|
+
export declare const PLATFORM: readonly string[];
|
|
139
|
+
/**
|
|
140
|
+
* The organizations this person works in: the token's `orgs` its claims open
|
|
141
|
+
* (`opened`). Empty for an account that has not made one, or that is only a plain
|
|
142
|
+
* member of a brand org: the SDK's own list falls back to the `owner` claim, which
|
|
143
|
+
* is the application's org and nobody's to work in.
|
|
136
144
|
*/
|
|
137
145
|
export declare function orgs(): string[];
|
|
138
146
|
/** The org of the person's own row: the first entry of the token's `orgs`, a directory or not. */
|
package/dist/lib/session.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* who was signed in, which reads as a permissions problem rather than a typo.
|
|
15
15
|
* Two derivations of one name never agree; this is the one derivation.
|
|
16
16
|
*/
|
|
17
|
-
import { superAdmin as
|
|
17
|
+
import { superAdmin as sudoOf } from '@hanzo/iam/browser';
|
|
18
18
|
import { api } from './api.js';
|
|
19
19
|
import { where } from '../where.js';
|
|
20
20
|
/** The SDK's own keys, `hanzo_iam_`-prefixed. The far side of a boundary. */
|
|
@@ -323,13 +323,45 @@ function listed(token) {
|
|
|
323
323
|
return out;
|
|
324
324
|
}
|
|
325
325
|
/**
|
|
326
|
-
* The
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
326
|
+
* The orgs the platform runs under its own names (hanzoai/authz claims.go
|
|
327
|
+
* `platformOrgs`): the brands and the estate's own namespaces. One is a tenant
|
|
328
|
+
* only of the people who run it, its owners and admins, and of a SuperAdmin; a
|
|
329
|
+
* customer who landed in a brand org as a plain member belongs to none of its
|
|
330
|
+
* data, and cloud refuses every request scoped to it.
|
|
331
|
+
*/
|
|
332
|
+
export const PLATFORM = [
|
|
333
|
+
'hanzo', 'lux', 'zoo', 'pars', 'platform', 'hanzoai', 'luxfi', 'zooai', 'hanzo-inc', 'hanzo-apps', 'hanzo-community',
|
|
334
|
+
];
|
|
335
|
+
/**
|
|
336
|
+
* The orgs a token opens to the person it names, home first, each once:
|
|
337
|
+
* hanzoai/authz `Claims.opens`, the rule cloud scopes every request by. A
|
|
338
|
+
* directory opens to no one, `admin` to a SuperAdmin, a platform org to its
|
|
339
|
+
* owners and admins and a SuperAdmin, and any other org to every member.
|
|
340
|
+
*/
|
|
341
|
+
function opened(token) {
|
|
342
|
+
const c = claimsOf(token);
|
|
343
|
+
const sudo = sudoOf(c);
|
|
344
|
+
const set = c?.orgs;
|
|
345
|
+
const out = [];
|
|
346
|
+
for (const ref of Array.isArray(set) ? set : []) {
|
|
347
|
+
const m = ref;
|
|
348
|
+
const o = m?.org;
|
|
349
|
+
if (typeof o !== 'string' || !o || out.includes(o) || DIRECTORIES.includes(o))
|
|
350
|
+
continue;
|
|
351
|
+
const runs = typeof m?.role === 'string' && ['owner', 'admin'].includes(m.role.trim().toLowerCase());
|
|
352
|
+
if (o === 'admin' ? sudo : PLATFORM.includes(o) ? sudo || runs : true)
|
|
353
|
+
out.push(o);
|
|
354
|
+
}
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* The organizations this person works in: the token's `orgs` its claims open
|
|
359
|
+
* (`opened`). Empty for an account that has not made one, or that is only a plain
|
|
360
|
+
* member of a brand org: the SDK's own list falls back to the `owner` claim, which
|
|
361
|
+
* is the application's org and nobody's to work in.
|
|
330
362
|
*/
|
|
331
363
|
export function orgs() {
|
|
332
|
-
return
|
|
364
|
+
return opened(bearer());
|
|
333
365
|
}
|
|
334
366
|
/** The org of the person's own row: the first entry of the token's `orgs`, a directory or not. */
|
|
335
367
|
export function home() {
|
|
@@ -452,7 +484,7 @@ export function choose() {
|
|
|
452
484
|
* organization and the step into one.
|
|
453
485
|
*/
|
|
454
486
|
export function superAdmin() {
|
|
455
|
-
return
|
|
487
|
+
return sudoOf(claims());
|
|
456
488
|
}
|
|
457
489
|
/** The organization a SuperAdmin stepped into through IAM, from the token's `assumed` claim, or null. */
|
|
458
490
|
export function assumed() {
|
|
@@ -488,7 +520,7 @@ export async function support(org) {
|
|
|
488
520
|
throw new Error(body?.msg || `IAM answered ${res.status}.`);
|
|
489
521
|
tokens().setItem(ACCESS, next);
|
|
490
522
|
tokens().setItem(EXPIRES, String(exp * 1000));
|
|
491
|
-
pick(org ??
|
|
523
|
+
pick(org ?? opened(next)[0] ?? '');
|
|
492
524
|
window.location.reload();
|
|
493
525
|
}
|
|
494
526
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/rooms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.87",
|
|
4
4
|
"description": "The workspace rooms — Home, Chat, Inbox, Contacts, Meet, Cal, Drive, Board, Work, Bots — and the frame that holds them, once, for every Hanzo surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|