Set Up a Team Knowledge Base

Create a shared team workspace with roles, permissions, invitations, and optional SCIM provisioning.

intermediate16 min read

What You'll Build

A team knowledge base in Lifestream Vault is a shared workspace where multiple people collaborate on documents in real time. Teams have their own vaults, role-based access control, and optional automated provisioning via SCIM.

By the end of this guide you will have:

  • A team with named members and role-based permissions
  • One or more shared vaults scoped to the team
  • An invitation workflow for onboarding new members
  • Optional SCIM 2.0 auto-provisioning for large organisations (Business tier)
  • A team calendar for tracking shared deadlines and events

Everything is available through the Lifestream Vault web UI, the TypeScript SDK, or the lsvault CLI.

Prerequisites

  • A Lifestream Vault account with Pro tier or higher (teams require Pro minimum)
  • Business tier to enable SCIM 2.0 auto-provisioning
  • Node.js 18+ (for SDK and CLI usage)

Create a Team

A team is the top-level organisational unit. It has a name, a set of members, and owns one or more shared vaults. The user who creates a team becomes its owner automatically.

Via the UI: open Settings → Teams → New Team, enter a team name, and click Create Team.

Or use the SDK or CLI:

typescript
import { LifestreamVaultClient } from '@lifestreamdynamics/vault-sdk';

const { client } = await LifestreamVaultClient.login(
  'https://vault.lifestreamdynamics.com',
  'you@example.com',
  'your-password',
);

const team = await client.teams.create({
  name: 'Engineering',
});

console.log('Team created:', team.id);
console.log('Team name:', team.name);

After the team is created, the team dashboard appears at Settings → Teams → Engineering. From here you can manage members, vaults, and settings.

Create Shared Vaults

Shared vaults are vaults owned by a team rather than an individual user. All team members can access the vault according to their role. A team can have multiple vaults — a common pattern is one per project, product, or department.

Create a vault and associate it with your team:

For multi-team instances, consider a consistent vault naming convention like team-engineering/docs or dept-marketing/assets. This makes it easier to manage permissions and discover content across the organization.

typescript
// createVault is positional: (teamId, { name, description? }).
// The slug is derived from the name server-side — you do not pass it.
const vault = await client.teams.createVault(team.id, {
  name: 'Engineering Docs',
});

console.log('Shared vault created:', vault.id);
console.log('Vault slug:', vault.slug);

// Create a second vault for runbooks
const runbooksVault = await client.teams.createVault(team.id, {
  name: 'Runbooks',
  description: 'Incident response and operational procedures',
});

console.log('Runbooks vault:', runbooksVault.id);

Team vaults are accessible to all team members with the appropriate role. Individual users who are not on the team cannot access the vault, even with a valid account.

Member Roles and Permissions

Every team member is assigned one of four roles. Roles apply across all vaults owned by the team.

RoleDescriptionCan ReadCan WriteCan DeleteCan Manage MembersCan Change Settings
viewerRead-only accessYesNoNoNoNo
editorCan create and edit documentsYesYesNoNoNo
adminCan manage members and vaultsYesYesYesYesNo
ownerFull control, including billing and deletionYesYesYesYesYes

Role Assignment Guidelines

  • Assign viewer to stakeholders and external reviewers who need to read but not write
  • Assign editor to active contributors — most team members will use this role
  • Assign admin to team leads who manage onboarding and vault organisation
  • Limit owner to one or two people who are responsible for the team account

You can change a member's role at any time from Settings → Teams → [Team Name] → Members, or via the SDK/CLI.

typescript
// updateMemberRole is positional: (teamId, userId, role)
await client.teams.updateMemberRole(team.id, 'user_xyz789', 'admin');

console.log('Member role updated to admin');

// List all members with their roles — listMembers takes the teamId directly
const members = await client.teams.listMembers(team.id);
for (const member of members) {
  console.log(`${member.user.displayName ?? member.user.email}: ${member.role}`);
}

Invite Team Members

Send email invitations to bring people into your team. Invited users receive an email with a secure link. If they don't have a Lifestream Vault account yet, the invitation flow guides them through registration.

Each invitation specifies the email address and the role the new member will receive upon accepting.

typescript
// inviteMember is positional: (teamId, email, role).
// Role must be one of 'admin' | 'editor' | 'viewer'.
const invite = await client.teams.inviteMember(team.id, 'alice@example.com', 'editor');

console.log('Invitation created:', invite.id);
console.log('Status:', invite.status); // 'pending'
console.log('Expires at:', invite.expiresAt);

// Invite multiple people at once
const newMembers = [
  { email: 'bob@example.com', role: 'editor' as const },
  { email: 'carol@example.com', role: 'viewer' as const },
  { email: 'dan@example.com', role: 'admin' as const },
];

for (const member of newMembers) {
  await client.teams.inviteMember(team.id, member.email, member.role);
  console.log(`Invited ${member.email} as ${member.role}`);
}

Invitations expire after 7 days by default. If a user does not accept within that window, revoke the expired invitation and create a new one (there is no resend operation). The link in the email is single-use and cannot be forwarded.

Managing Invitations

You can list and revoke pending invitations at any time. This is useful when you made a mistake in the role, or when you need to tighten access before an invitation is accepted. (There is no resend operation — revoke the stale invitation and create a new one.)

typescript
// listInvitations takes the teamId directly and returns TeamInvitation[]
const invitations = await client.teams.listInvitations(team.id);

const pending = invitations.filter((i) => i.status === 'pending');
console.log(`${pending.length} pending invitations:`);
for (const inv of pending) {
  console.log(` - ${inv.email} (${inv.role}) — expires ${inv.expiresAt}`);
}

// There is no resendInvitation — to refresh an invite, revoke it and
// create a new one with inviteMember(teamId, email, role).

// Revoke an invitation before it is accepted — positional: (teamId, invitationId)
await client.teams.revokeInvitation(team.id, invitations[0].id);
console.log('Invitation revoked');

SCIM Auto-Provisioning

Plan Required

SCIM 2.0 provisioning requires a Business plan. Upgrade in Settings → Subscription.

SCIM 2.0 (System for Cross-domain Identity Management) allows your Identity Provider (Okta, Azure AD, Google Workspace, etc.) to automatically provision and deprovision users in Lifestream Vault. When an employee joins your organisation, their IdP creates their Vault account automatically. When they leave, their access is revoked.

Setup Overview

  1. Generate a SCIM token in Lifestream Vault
  2. Configure your IdP with the SCIM base URL and token
  3. Map IdP groups to Lifestream Vault teams in your IdP
  4. Enable SCIM provisioning in the IdP — users are synced automatically

The SCIM base URL is:

https://vault.lifestreamdynamics.com/api/v1/scim/v2

Authentication uses a Bearer token that you generate in the Vault admin panel.

bash
# The SCIM Bearer token is a static server-side environment variable.
# Set SCIM_TOKEN in your API environment and restart the server.
# Provide this token to your IdP as the SCIM bearer token.

# Generate a secure random token:
openssl rand -hex 64

# Add to your API config:
# SCIM_TOKEN=<generated value>

# Then restart the API:
pm2 restart lsvault-api

# SCIM Base URL for your IdP:
echo "https://vault.lifestreamdynamics.com/api/v1/scim/v2"

SCIM Base URL: https://vault.lifestreamdynamics.com/api/v1/scim/v2

Supported SCIM operations: GET /Users, POST /Users, GET /Users/:id, PUT /Users/:id, PATCH /Users/:id, DELETE /Users/:id, GET /Groups, POST /Groups, PATCH /Groups/:id

The SCIM endpoint is authenticated with a Bearer token in the Authorization header. Your IdP handles this automatically once configured.

Team Calendar

The team calendar aggregates all calendar events across team vaults into a single shared view. Team members can see due dates, scheduled events, and booking slots across all team-owned vaults without switching between individual vault calendars.

Via the UI: open your team dashboard and click Calendar in the sidebar.

Key features:

  • Document due dates — any document with a due: frontmatter field appears on the calendar
  • Scheduled events — calendar events created within team vaults are visible to all members
  • Activity heatmap — shows document activity (creates, updates) by day across the team
  • Team booking groups — coordinate availability across multiple team members (Business tier)
typescript
// getCalendarEvents is positional: (teamId, { start?, end? }) -> CalendarEvent[]
const events = await client.teams.getCalendarEvents(team.id, {
  start: new Date().toISOString(),
  end: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), // next 30 days
});

console.log(`${events.length} upcoming team events:`);
for (const event of events) {
  console.log(` - [${event.startDate}] ${event.title} (vault: ${event.vaultId})`);
}

// Fetch upcoming due documents across the team — getDue(teamId, { status? })
const dueSoon = await client.teams.getDue(team.id, { status: 'upcoming' });

console.log(`${dueSoon.length} upcoming due documents`);

Tips & Best Practices

Onboarding New Members

Create an onboarding.md document in your team vault that every new member reads first. Include:

  • How your team uses the knowledge base (what goes in, what doesn't)
  • Vault structure and naming conventions
  • Who to contact with questions
  • Links to important documents

Pin it to the top of the vault with a pinned: true frontmatter field.

Vault Organisation for Teams

A common pattern is one vault per concern:

Engineering team vaults:
├── eng-docs/          # Architecture decisions, technical references
├── runbooks/          # Incident response and operational procedures
├── rfcs/              # Request-for-Comment documents for major changes
└── meeting-notes/     # Team meeting summaries and action items

Keep vault purposes narrow and well-defined. A catch-all "everything" vault becomes hard to navigate as the team grows.

Naming Conventions

Agree on naming conventions before the vault fills up:

  • Document paths: YYYY-MM-DD-title.md for dated content (meeting notes, decisions)
  • Folder names: lowercase, hyphenated (e.g. api-design, incident-reports)
  • Frontmatter: always include title, date, and author (or authors) in team documents

Using Tags for Cross-Vault Discovery

Tags are searchable across all vaults a user has access to. Standardise tags like #decision, #draft, #needs-review, and #deprecated so team members can find content regardless of which vault it lives in.

Webhooks for Team Notifications

Set up a webhook on the document.created and document.updated events pointing to a Slack incoming webhook URL. This way, the team sees new content in their existing communication channels without having to check the vault dashboard manually.

Regular Grooming

Schedule a monthly knowledge base grooming session where the team:

  1. Archives stale or outdated documents
  2. Resolves broken wikilinks
  3. Reviews documents tagged #needs-review
  4. Updates the onboarding guide

What's Next

Your team knowledge base is up and running. Here are some directions to explore next: