Marvia

Sign inSign up

Marvia-06

Workspace first. Nothing exists outside one.

The Identity & Workspace Engine is the dependency foundation for every later module. Authentication is one entry point into it, never the whole of it.

Providers

3 / 8

Roles

6

Permissions

33

Identity events

18

User → Membership → Workspace → Role → Permissions → Context

Principles

Four rules the engine never breaks

Workspace first

Every resource belongs to a workspace. Nothing exists outside one, so isolation is structural rather than a rule people remember.

Identity is not authentication

Authentication is one entry point into the identity system. Providers are data; adding Passkeys or SAML changes a table, not the kernel.

Permission awareness

Every operation validates workspace membership and a named permission before it touches a repository.

Guest conversion by design

A guest reaches real value first. Sign-in claims the work already done instead of discarding it.

Authentication

Providers are data, not branches

Google and GitHub are live. Everything else is already modelled, hidden until it is switched on.

ProviderKindStatusIn auth UI
googleoauthactivevisible
githuboauthactivevisible
email-inviteemailactivehidden
magic-linkemailplannedhidden
email-passwordemailplannedhidden
passkeywebauthnplannedhidden
sso-oidcoidcplannedhidden
sso-samlsamlplannedhidden
Google · activeGitHub · activeMicrosoft · plannedApple · plannedLinkedIn · plannedX · planned

Guest mode

Value before the sign-in wall

A guest can analyse, preview and browse. Anything that persists, spends or connects asks for an account at the moment it matters.

Allowed

  • analyze-website
  • preview-report
  • browse-marketplace
  • read-learning-content
  • preview-documentation

Requires an account

  • save-report
  • create-workspace
  • install-extension
  • purchase-credits
  • connect-service
  • generate-ai-action
  • access-history

Workspace lifecycle

Six operations, each with a permission and an event

A transition that is not in this table cannot happen. Deletion is soft; purging belongs to retention, not to a feature.

OperationFromToPermissionEvent
createactiveworkspace.readworkspace.created
renameactiveactiveworkspace.updateworkspace.updated
archiveactivearchivedworkspace.archiveworkspace.archived
restorearchivedactiveworkspace.restoreworkspace.restored
transferOwnershipactiveactiveworkspace.transferworkspace.ownership.transferred
softDeleteactive, archiveddeletedworkspace.deleteworkspace.deleted

Creation flow

  1. 1. Workspace nameOne field. A slug is derived and can change later.
  2. 2. Workspace iconOptional. Defaults to a generated monogram.
  3. 3. DoneMembers, theme, locale and AI providers are settings, not blockers.

Empty state

  • Analyze a websiteRuns a snapshot and a preview report in one step.
  • Connect Search ConsoleBrings real query data into the workspace.
  • Browse extensionsAdds surfaces without touching the kernel.
later · permanentDeletelater · customSluglater · logolater · themelater · localelater · timezonelater · aiProvider

RBAC

Roles live on the membership, never on the user

A user holds a different role in every workspace. Permissions are granular and named; features ask for a permission, not for a role.

owner

33

Full control, including deletion and ownership transfer.

admin

31

Manages members, permissions, connectors and extensions.

editor

17

Creates and modifies content, projects and reports.

member

15

Works inside the workspace and spends credits.

viewer

9

Read-only across every workspace surface.

guest

3

Scoped, time-boxed read access. Reserved for future use.

workspace.readworkspace.updateworkspace.archiveworkspace.restoreworkspace.deleteworkspace.transfermember.readmember.invitemember.updatemember.removerole.assignproject.readproject.writeproject.deletereport.readreport.generatereport.exportcredits.readcredits.consumecredits.purchaseextension.readextension.installextension.configureextension.approveconnector.readconnector.managecontent.readcontent.writecontent.publishsettings.readsettings.updatehistory.readaudit.read

Invitations

Email and link invites with a bounded lifetime

Tokens are single use and hashed at rest. Expiry, revocation and resend are part of the contract, not follow-up work.

Policy

  • expiryDays: 7
  • maxPendingPerWorkspace: 50
  • resendCooldownMinutes: 10
  • singleUse: true

Lifecycle

issued → delivered → opened → accepted

Sessions & security

Cookies the browser cannot read

Sessions rotate, devices are listable and revocable, and every security event lands in the tamper-evident audit chain.

Session policy

  • cookieName: marvia_session
  • httpOnly: true
  • sameSite: lax
  • secure: true
  • idleMinutes: 10080
  • absoluteDays: 30
  • rememberMeDays: 90
  • rotateEveryMinutes: 60

Threat controls

  • csrfState-changing requests carry a double-submit CSRF token bound to the session.
  • oauth-stateOAuth state and PKCE verifier are generated server side and validated on callback.
  • rate-limitSign-in, invitation and callback routes are rate limited per IP and per identity.
  • rotationSession identifiers rotate on sign-in, role change and workspace transfer.
  • no-browser-secretsProvider secrets and tokens live server side only; the browser sees a cookie.
  • auditEvery security event appends an audit_logs row: sign-in, revoke, role change, invite.

Services & events

Nine services, nine repositories, one event contract

Services own behaviour, repositories own persistence, and the event bus is how everything else finds out.

Services

  • IdentityService
  • SessionService
  • ProfileService
  • WorkspaceService
  • MembershipService
  • PermissionService
  • RoleService
  • InvitationService
  • ContextService

Repositories

  • UserRepository
  • ProfileRepository
  • ConnectedAccountRepository
  • SessionRepository
  • WorkspaceRepository
  • MemberRepository
  • RoleRepository
  • PermissionRepository
  • InvitationRepository

Events

  • workspace.created
  • workspace.updated
  • workspace.archived
  • workspace.restored
  • workspace.deleted
  • workspace.ownership.transferred
  • workspace.member.joined
  • workspace.member.role.updated
  • workspace.member.removed
  • workspace.invitation.sent
  • workspace.invitation.accepted
  • user.created
  • user.updated
  • user.deleted
  • session.created
  • session.revoked
  • permission.updated
  • guest.converted

Constraints

Permanent, non-negotiable

  • Identity isolation — no report, credit or billing logic ever lives in the identity layer.
  • Workspace context — every operation validates membership and permission, never ambient state.
  • Provider agnosticism — no vendor auth. Better Auth is an adapter behind AuthAdapter.
  • Guest conversion — the guest-to-user transition preserves snapshots and reports.