From 2290368b9d225f7049b4867e2fbea3f5905ffd64 Mon Sep 17 00:00:00 2001 From: Sam Clemente Date: Thu, 20 Aug 2026 19:51:42 -0500 Subject: [PATCH] feat(auth): detail community bookmark permissions Names the canonical bookmark collection and explains its create, update, and delete access separately on the login disclosure. --- apps/web/src/app/login/page.tsx | 21 ++++++++++++++++ apps/web/src/lib/oauthScopeDisclosure.test.ts | 24 +++++++++++++++++++ apps/web/src/lib/oauthScopeDisclosure.ts | 22 +++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/apps/web/src/app/login/page.tsx b/apps/web/src/app/login/page.tsx index 2115dbd..af5bb37 100644 --- a/apps/web/src/app/login/page.tsx +++ b/apps/web/src/app/login/page.tsx @@ -178,6 +178,27 @@ export default function LoginPage() {
{group.title}
{group.detail}
+ {group.collection ? ( +
+ + {group.collection} + +
+ ) : null} + {group.permissions ? ( +
+
    + {group.permissions.map((permission) => ( +
  • + + {permission.action}: + {" "} + {permission.detail} +
  • + ))} +
+
+ ) : null}
))} diff --git a/apps/web/src/lib/oauthScopeDisclosure.test.ts b/apps/web/src/lib/oauthScopeDisclosure.test.ts index 51e4caa..b544863 100644 --- a/apps/web/src/lib/oauthScopeDisclosure.test.ts +++ b/apps/web/src/lib/oauthScopeDisclosure.test.ts @@ -16,6 +16,30 @@ describe("OAuth scope disclosure", () => { expect(OAUTH_SCOPE_DISCLOSURE_GROUPS.at(-1)?.webOnly).toBe(true); }); + test("breaks out community bookmark record access by action", () => { + const bookmarkGroup = OAUTH_SCOPE_DISCLOSURE_GROUPS.find( + ({ title }) => title === "Bookmarks" + ); + + expect(bookmarkGroup?.collection).toBe( + "community.lexicon.bookmarks.bookmark" + ); + expect(bookmarkGroup?.permissions).toEqual([ + { + action: "Create", + detail: "Save links as new public bookmark records.", + }, + { + action: "Update", + detail: "Edit tags on existing bookmark records.", + }, + { + action: "Delete", + detail: "Remove bookmark records from your repository.", + }, + ]); + }); + test("states the important access limitations", () => { expect(OAUTH_SCOPE_LIMITATION_DISCLOSURE).toContain("cannot post to feeds"); expect(OAUTH_SCOPE_LIMITATION_DISCLOSURE).toContain("read messages or email"); diff --git a/apps/web/src/lib/oauthScopeDisclosure.ts b/apps/web/src/lib/oauthScopeDisclosure.ts index fc9decf..bce417c 100644 --- a/apps/web/src/lib/oauthScopeDisclosure.ts +++ b/apps/web/src/lib/oauthScopeDisclosure.ts @@ -1,6 +1,13 @@ +export type OAuthScopeDisclosurePermission = Readonly<{ + action: "Create" | "Update" | "Delete"; + detail: string; +}>; + export type OAuthScopeDisclosureGroup = Readonly<{ title: string; detail: string; + collection?: string; + permissions?: readonly OAuthScopeDisclosurePermission[]; webOnly?: boolean; }>; @@ -8,6 +15,21 @@ export const OAUTH_SCOPE_DISCLOSURE_GROUPS: readonly OAuthScopeDisclosureGroup[] { title: "Bookmarks", detail: "Create, update, and delete community bookmark records in your public repository.", + collection: "community.lexicon.bookmarks.bookmark", + permissions: [ + { + action: "Create", + detail: "Save links as new public bookmark records.", + }, + { + action: "Update", + detail: "Edit tags on existing bookmark records.", + }, + { + action: "Delete", + detail: "Remove bookmark records from your repository.", + }, + ], }, { title: "Reading State",