mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 14:59:39 +02:00
Second milestone of the unlisted-share rollout. Backend endpoints
from M8.1 are now callable from the client, and a reusable
SharedLinkControls component is available for the detail views that
wire up in M8.3/M8.4.
Scope: shared primitives only. No module store integrates them yet —
that's the next step per module.
Changes:
- @mana/shared-privacy/unlisted-client.ts:
publishUnlistedSnapshot(opts) → { token, url }
Idempotent per (collection, recordId) — server reuses token on
re-publish, so store code can call on every edit without caring
whether it's first publish or refresh.
revokeUnlistedSnapshot(opts)
Idempotent — resolves silently even on { revoked: 0 }.
buildShareUrl(origin, token)
Convenience for UIs that already know the token.
UnlistedApiError
Thrown on non-2xx. Carries { status, code } so callers can
distinguish 400 COLLECTION_NOT_ALLOWED vs 410 REVOKED vs
500 UNKNOWN.
- @mana/shared-privacy/SharedLinkControls.svelte:
Dumb presentational component. Props: token, url, expiresAt,
onRegenerate, onRevoke, onExpiryChange (optional), disabled.
Renders URL + copy, regenerate with confirm dialog, revoke,
optional datetime-local expiry picker, debug token fingerprint.
Clipboard-API fallback to prompt() for unsecure origins.
QR-code button deferred to M8.5 polish.
- Exports added to index.ts: functions, error class, both types,
SharedLinkControls component.
- 10 new unit tests (25 total): publish URL shape, headers, body,
expiresAt serialisation, 4xx/5xx handling, trailing-slash
trimming on apiUrl, revoke idempotence, buildShareUrl join.
Verified:
- pnpm --filter @mana/shared-privacy test: 25/25 green
- pnpm --filter @mana/shared-privacy check: 0 errors
- pnpm --filter @mana/web check: 7531 files, 0 errors
Next: M8.3 — wire Calendar through the new client.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
/**
|
|
* @mana/shared-privacy
|
|
*
|
|
* Unified visibility/privacy primitives for every Mana module. Provides:
|
|
*
|
|
* - VisibilityLevel enum: 'private' | 'space' | 'unlisted' | 'public'
|
|
* - Zod schema for validation at the record/schema layer
|
|
* - Default helper (derives private vs space from the active space type)
|
|
* - Predicates for publish-time gating (canEmbedOnWebsite, …)
|
|
* - Unlisted-token generator (32-char base64url, CSPRNG)
|
|
* - <VisibilityPicker> Svelte component for the consistent UI control
|
|
*
|
|
* Design + rollout: docs/plans/visibility-system.md.
|
|
*
|
|
* Import path stays flat:
|
|
* import {
|
|
* VisibilityLevelSchema,
|
|
* canEmbedOnWebsite,
|
|
* VisibilityPicker,
|
|
* } from '@mana/shared-privacy';
|
|
*/
|
|
|
|
export type { VisibilityLevel, VisibilityMeta, VisibilityChangedPayload } from './types';
|
|
export { VISIBILITY_LEVELS, VISIBILITY_METADATA } from './types';
|
|
export { VisibilityLevelSchema, UnlistedTokenSchema } from './schema';
|
|
export { defaultVisibilityFor } from './defaults';
|
|
export {
|
|
canEmbedOnWebsite,
|
|
isReachableByLink,
|
|
isVisibleToSpaceMember,
|
|
canAiAccessCrossUser,
|
|
} from './predicates';
|
|
export { generateUnlistedToken } from './tokens';
|
|
|
|
export {
|
|
publishUnlistedSnapshot,
|
|
revokeUnlistedSnapshot,
|
|
buildShareUrl,
|
|
UnlistedApiError,
|
|
type PublishUnlistedOptions,
|
|
type PublishUnlistedResult,
|
|
type RevokeUnlistedOptions,
|
|
} from './unlisted-client';
|
|
|
|
export { default as VisibilityPicker } from './VisibilityPicker.svelte';
|
|
export { default as SharedLinkControls } from './SharedLinkControls.svelte';
|