Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Deploy Docs

on:
push:
branches: [develop]
workflow_dispatch:

concurrency:
group: docs
cancel-in-progress: true

env:
NODE_VERSION: '22'
PNPM_VERSION: '12.3.4'

jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Generate package API docs
run: pnpm run docs

- name: Build docs site
run: pnpm --filter @inftkr/docs build

- name: Verify static export
run: test -f apps/docs/out/index.html

- name: Publish to gh-pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: apps/docs/out
force_orphan: true
publish_branch: gh-pages

- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy apps/docs/out --project-name=inft-auth-docs
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ temp/
# turbo
.turbo/

# generated docs
docs/
# generated docs (package API artifacts; root docs/ guide is tracked)
**/docs/
!/docs/
!/apps/docs/

# fumadocs generated content
.source
apps/docs/content/api/

# env / secrets
.env
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The first consuming service is **Tailscale** (custom OIDC client).
apps/
backend/ # Nest.js + oidc-provider — OIDC/OAuth2 server, session API
www/ # Next.js — frontend UI only (login, consent, management)
docs/ # Fumadocs — static documentation site (guides + API reference)
packages/
shared/ # @inftkr/shared — shared constants & domain types
auth-core/ # @inftkr/auth-core — shared auth core: types, client, guards, react hooks
Expand Down Expand Up @@ -61,13 +62,25 @@ pnpm run docs # turbo run docs (API docs generation)

## Documentation

Operation guides live in the `docs/` directory as MDX sources and are published
as a static site (`apps/docs`, Fumadocs) covering host `auth.inft.kr` / `inft.kr`,
deployment, security model, OIDC integration and per-package API references.

Each package generates per-member API documentation in Markdown into its
`docs/` directory via a TypeDoc-free pipeline:

1. `build:docs` — emit declarations to `dist-docs/`
2. `api-extractor run --local` — produce `api-report.api.md` + `docs.api.json`
3. `generate-split-documentation` — split the doc model into per-member files

The docs site build (`apps/docs`) consumes `docs.api.json` to render the API
reference automatically; run it with:

```bash
pnpm run docs # regenerate package API artifacts
pnpm --filter @inftkr/docs build # static export into apps/docs/out/
```

## Related

- Tracked issue with the full roadmap: https://github.com/InfiniteTeam/auth/issues/4
38 changes: 38 additions & 0 deletions apps/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# @inftkr/backend

Nest.js API for the [inft-auth](https://github.com/InfiniteTeam/auth) identity
platform. Implements OAuth 2.0 / OpenID Connect directly on
[oidc-provider](https://github.com/panva/node-oidc-provider) and exposes the
session API consumed by the frontend (`apps/www`).

## Responsibilities

- **OIDC provider** — authorization endpoint, token introspection, JWKS, dynamic
client registration via `oidc-provider`
- **LDAP authentication** — validates credentials against lldap over LDAP
- **Session management** — `inft_session` cookie
(`HttpOnly; Secure; SameSite=Lax`), Prisma-backed persistence in the `auth`
database schema
- **Social login** — GitHub / Discord OAuth, with a strict no-auto-merge policy

## API contract

Endpoints (source of truth: `@inftkr/auth-core` `AuthApiClient`):

| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/api/v1/session` | current session, `401` when unauthenticated |
| `POST` | `/api/v1/auth/ldap` | LDAP sign-in with `{ email, password }` |
| `POST` | `/api/v1/auth/social/:provider` | start social sign-in (`github` / `discord`) |
| `DELETE` | `/api/v1/session` | sign out (`204`) |

See `.env.example` for the full configuration surface.

## Development

```bash
pnpm dev # nest start --watch
pnpm test # vitest run
pnpm typecheck # tsc --noEmit
pnpm build # nest build
```
16 changes: 16 additions & 0 deletions apps/docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# deps
/node_modules

# generated content (produced by scripts/prepare-content.mjs)
/content

# test & build
/.next/
/out/
/build
*.tsbuildinfo

# misc
.DS_Store
.env*.local
next-env.d.ts
32 changes: 32 additions & 0 deletions apps/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# @inftkr/docs

Static documentation site for [inft-auth](https://github.com/InfiniteTeam/auth)
built with [Fumadocs](https://fumadocs.dev) on Next.js static export.

## Content

- **Guides** — operation docs sourced from the repository-root `docs/*.mdx`
- **API reference** — generated from each package's `docs.api.json`
(api-extractor doc model) via `scripts/prepare-content.mjs`

The API reference is rendered automatically whenever package API docs are
regenerated with `pnpm run docs` at the repository root.

## Development

```bash
pnpm dev # next dev (predev regenerates content)
pnpm build # next build → static export into out/
pnpm start # serve out/ locally
pnpm typecheck # tsc --noEmit
```

## Layout

```
content/ # built locally (gitignored), never edited by hand
guides/ # copies of docs/*.mdx
api/ # generated from packages/*/docs/docs.api.json
scripts/
prepare-content.mjs # content preparation (predev/prebuild)
```
6 changes: 6 additions & 0 deletions apps/docs/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/lib/layout.shared';

export default function Layout({ children }: LayoutProps<'/'>) {
return <HomeLayout {...baseOptions()}>{children}</HomeLayout>;
}
71 changes: 71 additions & 0 deletions apps/docs/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Fingerprint, LockKeyhole, ShieldCheck, BookOpenCheck, Code2 } from 'lucide-react';
import { FeatureCards } from '@/components/feature-cards';

const features = [
{
icon: Fingerprint,
title: 'OAuth 2.0 / OIDC',
description:
'Standards-compliant provider built on oidc-provider with a Nest.js backend.',
href: '/docs/oidc',
hrefText: 'OIDC & integrations',
},
{
icon: ShieldCheck,
title: 'LDAP identity',
description:
'User identities managed by lldap (PostgreSQL-backed, single source of truth).',
href: '/docs/security',
hrefText: 'Security model',
},
{
icon: LockKeyhole,
title: 'Session & cookies',
description:
'Signed inft_session cookie — HttpOnly, Secure, SameSite=Lax, 7-day TTL.',
href: '/docs/security',
hrefText: 'Security model',
},
];

export default function HomePage() {
return (
<div className="mx-auto flex w-full max-w-4xl flex-col gap-10 px-6 py-16 md:py-24">
<div className="text-center">
<p className="mb-4 text-xs font-bold uppercase tracking-[0.15em] text-fd-primary">
InfiniteTeam identity platform
</p>
<h1 className="text-4xl font-semibold tracking-tight md:text-6xl">
One account,{' '}
<span className="bg-gradient-to-r from-[#6ee7b7] to-[#5eead4] bg-clip-text text-transparent">
every service
</span>
</h1>
<p className="mx-auto mt-6 max-w-2xl text-base leading-relaxed text-fd-muted-foreground md:text-lg">
Self-hosted authentication for the InfiniteTeam ecosystem — OAuth 2.0 /
OpenID Connect, LDAP identity, WebFinger and social login. The first
consuming service is Tailscale (custom OIDC client).
</p>
</div>

<FeatureCards features={features} />

<div className="flex flex-wrap items-center justify-center gap-3">
<a
href="/docs"
className="inline-flex items-center gap-2 rounded-lg bg-[#40d88c] px-5 py-2.5 text-sm font-semibold text-[#071b13] transition hover:bg-[#5eead4]"
>
<BookOpenCheck className="size-4" />
Read the docs
</a>
<a
href="https://github.com/InfiniteTeam/auth"
className="inline-flex items-center gap-2 rounded-lg border border-[--fd-border] px-5 py-2.5 text-sm font-semibold text-fd-foreground transition hover:bg-fd-secondary"
>
<Code2 className="size-4" />
View on GitHub
</a>
</div>
</div>
);
}
9 changes: 9 additions & 0 deletions apps/docs/app/api/search/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

export const revalidate = false;

export const { staticGET: GET } = createFromSource(source, {
// https://docs.orama.com/docs/orama-js/supported-languages
language: 'english',
});
65 changes: 65 additions & 0 deletions apps/docs/app/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';

/*
* The documentation site inherits the platform portal design used by `apps/www`
* (`feat/nextjs-portal` theme): a deep navy background with a mint gradient
* accent. The portal palette is mapped onto Fumadocs' `--color-fd-*` tokens so
* every component picks up the InfiniteTeam look automatically.
*/
:root {
--font-sans: Pretendard, Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI',
sans-serif;
--font-heading: var(--font-sans);
--radius: 0.75rem;
}

:root,
.dark {
color-scheme: dark;

--color-fd-background: #151824;
--color-fd-foreground: #f7faf9;
--color-fd-card: #181b28;
--color-fd-card-foreground: #f7faf9;
--color-fd-popover: #181b28;
--color-fd-popover-foreground: #f7faf9;
--color-fd-primary: #40d88c;
--color-fd-primary-foreground: #071b13;
--color-fd-secondary: #1d2130;
--color-fd-secondary-foreground: #f7faf9;
--color-fd-muted: #1d2129;
--color-fd-muted-foreground: #929aa8;
--color-fd-accent: #1d2130;
--color-fd-accent-foreground: #f7faf9;
--color-fd-border: rgba(255, 255, 255, 0.1);
--color-fd-ring: #5eead4;
--color-fd-overlay: hsla(0, 0%, 0%, 0.4);
}

html {
scrollbar-gutter: stable;
}

html > body[data-scroll-locked] {
margin-right: 0px !important;
--removed-body-scroll-bar-size: 0px !important;
}

body {
font-family: var(--font-sans);
background: radial-gradient(
circle at 8% 0%,
rgba(64, 216, 140, 0.08),
transparent 30rem
),
var(--color-fd-background);
}

a {
color: #6ee7b7;
}
a:hover {
color: #99f6e4;
}
12 changes: 12 additions & 0 deletions apps/docs/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Provider } from '@/components/provider';
import './global.css';

export default function Layout({ children }: LayoutProps<'/'>) {
return (
<html lang="ko" className="dark" suppressHydrationWarning>
<body className="flex flex-col min-h-screen">
<Provider>{children}</Provider>
</body>
</html>
);
}
Loading