akif/arclet-boards

Arclet Boards — private Kanban workspaces with AppID, DataK3, shared web and MCP actions.

A remix template · 1 remixes · Remix akif/arclet-boards

README.md

Arclet Boards

A little clarity for everything ahead. Arclet is a private Kanban workspace for teams, built on the official Dodil Boards Challenge starter. One FastAPI app serves a responsive web interface, an authenticated JSON API, and one action-oriented MCP endpoint. All three use the same authorized use cases.

See STATUS.md and evidence/ for actual test results, deployed user isolation checks, browser evidence, and the latest remix status.

What it does

  • Multiple workspaces and private boards, with board-specific owner/member/viewer roles. Workspace membership alone never reveals private boards.
  • Create and edit boards; create, rename, reorder and mark lists as completed.
  • Create, edit and drag cards across lists or reorder them within a list. Card details provide a keyboard/touch move control as well.
  • Descriptions, board-member assignment, due dates, colored labels, manual checklists, and a readable activity trail with actor, time and before/after data.
  • Owner-only invitations, role changes and removal. Removing someone clears their assignments in the same transaction, with history.
  • My tasks and automatic overdue views. Dates are UTC calendar dates; cards in completed lists are excluded from overdue results.
  • Conflicting edits return 409. Every mutation takes an idempotency key, so an interrupted request can be retried without creating duplicate cards or history.
  • Same-board prerequisites with cycle prevention, clear blocking chains, and safe completion/reopening rules.
  • Reviewable checklist drafts from saved card descriptions, using Dodil Kimi.
  • Daily briefs with real counts and activity; AI focus is restricted to existing card IDs and rendered using their actual titles.
  • Similar-card search using Dodil Jina embeddings and DataK3 VECTOR(512) cosine KNN. Editors explicitly build/refresh search; stale embeddings are excluded.

An invitation grants application access by email; it does not send an email or provision an AppID account. Share the board link. The invited person signs up or signs in through the attached pool using that address. The first accepted invitation binds to their immutable AppID subject.

Remix into your organization

Use CLI 0.1.91 or later and an organization where you have git.admin:

dodil auth login --web
dodil git remix plan akif/arclet-boards --to-org <your-org> --name arclet-boards
dodil git remix akif/arclet-boards --to-org <your-org> --name arclet-boards

Review the plan. It creates one bucket, one pool, one service account, and the repository; the generated credentials go directly to the new repository's CI secrets. No API keys need to be copied. Models access is granted for optional Dodil-only AI. Ordinary board editing does not call inference. AI buttons and semantic-index refresh consume the target organization's existing Dodil model allowance/credits; no outside model key is needed and the app buys no credits.

Keep the chosen repository name at 18 characters or fewer. The bucket name is ${repo}-data, with a 25-character limit and space for a fork suffix. Bucket and pool conflicts fail intentionally; they must never silently suffix away from the names in deploy.yaml.

After the remix — required before inviting a team

dodil ignite app get arclet-boards -o json
dodil appid settings get arclet-boards-users -o json
dodil appid settings set arclet-boards-users --require-email-verification=true

The verification setting is required because pending invitations are addressed by email. Do not admit unverified email signups to a pool used for invitations. Admin-created users are verified by default; ordinary signups must verify their address before login. Retain existing pool settings and callback entries.

Current Dodil Git automatically registers the app's sign-in callback during deployment (verified on the starter remix). Check the deploy log. If registration was not performed, add the callback using the actual host from public_urls:

dodil appid settings set arclet-boards-users --redirect-uris https://<actual-host>/.dodil/auth/callback

Never construct the host from the org name; Dodil escapes some characters. If signup is disabled, provision the first people with dodil appid user create arclet-boards-users you@example.com --roles member; they set their password through the pool's recovery flow. Passwords and tokens must not be pasted into this repository or terminal logs.

Open the app in a private browser window, sign in, create a workspace and board, then grant members access. Each new account starts without anyone else's boards.

Optionally apply the included hosted sign-in theme:

dodil appid branding set arclet-boards-users @appid-branding.json

Check the template and its target plan with:

dodil git remix check <org>/arclet-boards
dodil git remix plan <org>/arclet-boards --to-org <another-org>

An actual fresh-organization remix is only verified when STATUS.md records it.

MCP: connect as yourself

Add the app's /mcp URL as a custom connector in Claude or ChatGPT. RFC 9728 discovery points at this copy's AppID pool. Sign in as your own pool user and complete consent. A newly registered OAuth client may need approval by the pool administrator: inspect it before approving it.

dodil appid client list arclet-boards-users
dodil appid client get arclet-boards-users <client-id>
dodil appid client approve arclet-boards-users <client-id>

Tools include list_boards, get_board, create_board, create_list, list_my_cards, list_overdue, add_card, update_card, move_card, assign_card, set_due_date, get_card_activity, invite_member, change_member_role, and manual checklist actions. Mutation tools require a unique request_id; reuse it for retries of that exact command. Read fresh versions before edits. There is no raw SQL/table tool and no identity argument.

Extras tools: suggest_checklist (draft only), apply_checklist, daily_summary, refresh_semantic_index, find_similar_cards, add_dependency, remove_dependency, and get_blocking_chain. Read fresh board/card versions before applying a draft, adding a dependency, or refreshing the semantic index.

The application MCP is separate from the infrastructure MCP used to build it. Platform and AppID service-client tokens are refused as end-user identities.

Architecture and security

app/domain           entities, input rules, versions, roles, overdue semantics
app/application      shared validated commands and authorized use cases
app/infrastructure   DataK3 transactions, gateway identity, Dodil Models adapter
app/web              thin API adapter and same-origin HTML/CSS/JavaScript
app/mcp              action tools derived from the same command contracts
tests                transactional double for unit/door tests only
schema.sql           explicit primary keys for every runtime table
.dodil               provision and deploy manifests
.github/workflows    Dodil Git CI, image build/push, then CD

DataK3 is the sole persistent application store. arclet_* tables intentionally leave a pre-existing starter's tables untouched. A fresh remix creates only the Arclet schema. Atomic multi-table writes combine content, ordering, activity and idempotency. Guarded reads and per-record versions prevent lost updates. The repository retries SQLSTATE conflicts as whole transactions and uses parameter binding for every value. Six connections per replica keep two replicas below DataK3's documented per-bucket concurrent-read ceiling.

Ignite strips incoming identity headers, verifies the AppID session or bearer, and injects identity. Arclet requires X-Dodil-Auth-Source: pool, matching user and token claims, the configured pool, an unexpired token, and human amr. Permissions live in the application layer and apply equally through MCP. Outsiders receive the same 404 as missing resources. The app has no DEV_USER fallback. Do not expose uvicorn directly to the public internet outside Ignite's trusted gateway.

Browser state is fetched from the backend; there is no localStorage database, runtime memory repository, demo seed, external identity provider, or outside AI key. Assets use a strict same-origin CSP. User content is escaped, and browser API writes reject cross-origin requests. Tokens stay out of page JavaScript.

Local development and tests (Windows)

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r app/requirements.txt pytest==9.2.0 PyYAML==6.0.3
.\.venv\Scripts\python.exe -m pytest -q tests

Run commands from the repository root. The app/mcp directory must not be placed at the top of sys.path where it would shadow the installed MCP package. Python 3.12 is the CI/container runtime; the local suite also runs on 3.14.

To run against your own DataK3 test bucket, supply BUCKET, PG_HOST, PG_PORT, DODIL_SERVICE_ACCOUNT_ID, DODIL_SERVICE_ACCOUNT_SECRET and DODIL_USER_POOL through your environment, then python -m uvicorn app.main:app --port 8080. Take connection targets from dodil data connect <bucket> and do not log its credential-bearing DSN. The app uses TLS verify-full with public CA roots. Local uvicorn has no login bypass; authenticated integration tests belong behind an Ignite AppID gateway. Unit-test identities do not prove live isolation.

Deployment

Before pushing CI/CD changes, run dodil git ci verify --repo arclet-boards. Push main to Dodil Git. Its own CI runs tests, builds the numeric non-root image, pushes into the org's registry, then deploys with .dodil/deploy.yaml once checks are green. Registry credentials are injected by Dodil; do not mint replacements.

Runtime environment:

VariableSource
BUCKET${dodil.repo}-data
PG_HOST, PG_PORTverified DataK3 endpoint
DODIL_USER_POOL${dodil.org}/${dodil.repo}-users
DODIL_SERVICE_ACCOUNT_ID, DODIL_SERVICE_ACCOUNT_SECRETgenerated repo CI secrets, passed by reference
MODELS_BASE, CHAT_MODELDodil Models configuration retained from the starter

GET /healthz checks the process only. A platform-authenticated POST / runs a credential/schema self-check and returns counts, never row contents. Platform principals still cannot invoke end-user API/MCP actions. Verify browser and MCP flows with actual pool users as well as the self-check.

Current limits and next work

See STATUS.md and DESIGN_DECISIONS.md. AI and dependency extras were added after the core's 33 real-user API/MCP and 15 real-browser checks passed. Their real Models/DataK3 integration has separate evidence; STATUS.md distinguishes that from deployed extras checks. Semantic indexing is bounded at 100 cards per board and the first 4,000 description characters per embedding. Summary focus selection considers up to 100 unfinished candidates; counts still include the whole board. Model availability, credits and response latency can affect AI actions; errors are shown without inventing results. Polling/realtime push, attachments, comments, board deletion, ownership transfer and email delivery are outside the current core. Board sizes are bounded at 100 lists and 5,000 cards; checklist items are bounded at 100 per card. Large-team performance requires a measured follow-up.

MIT license. Original starter attribution is preserved in LICENSE and Git history.