/15 min read
architecting motherboard: polymorphic iam, forensic digital signatures, and operations at teen-builder scale
by Akshat Kushwaha
when you run an independent builder network across a dozen Indian cities with hundreds of teenage hackers, off-the-shelf SaaS tools fall apart surprisingly fast.
the official reason people buy twelve different enterprise subscriptions is “operational efficiency.” the more honest reason is that nobody wants to write the glue code. but when you are a registered Section 8 non-profit operating on a shoestring budget, paying $25 per user per month for identity, signature workflows, scheduling, and contract triage is financial suicide.
worse than the cost is the fragmentation. your community lives on Discord, your city leads track events in Notion, your banking runs through RazorpayX, and your legal agreements need to hold up under Indian court admissibility. when those systems don't talk to each other, volunteers spend half their week copy-pasting UUIDs and chasing signatures instead of shipping code.
so we built Motherboard (bnb-motherboard).
it started as an internal operations hub for the bits&bytes network (gobitsnbytes.org). over 56 development sessions and 190+ automated tests, it evolved into a full operational core: a hybrid monorepo coupling a Python FastAPI backend with a Next.js 15 cockpit dashboard, powering polymorphic IAM, Discord guild synchronization, Cal.com scheduling with native MIME calendar RSVPs, an automated contract review assistant, and an end-to-end digital signature engine built for statutory compliance under Indian law.
the hybrid monorepo: bun on the outside, uv on the inside#
most monorepos pick one language and force everything into it. if you pick TypeScript everywhere, you end up writing clumsy Python subprocesses for cryptographic PDF manipulation and AI diarization pipelines. if you pick Python everywhere, you give up modern React Server Components, streaming UI, and fluid animations.
we structured Motherboard as a hybrid monorepo:
- Frontend (
apps/web,packages/ui): Bun-managed Next.js 15 App Router with React 19, Tailwind CSS, Framer Motion, and custom neobrutalist components. - Backend (
apps/api): Python 3.12 managed with Astral'suv, running FastAPI, SQLAlchemy 2.0 withasyncpg, Alembic migrations, and Pydantic v2. - Shared packages & plugins (
packages/ui,plugins/*): dynamic plugin SDK allowing first-party and city-fork tools to register isolated routes and UI panels.
polymorphic IAM and sub-millisecond policy evaluation#
access control in distributed community organizations is messy. you have global executive leadership, city fork leads (e.g. Delhi, Bengaluru, Kolkata), technical track contributors, and temporary event volunteers.
most access management libraries force you into one of two traps:
- rigid role-based access control (RBAC): you create dozens of hyper-specific roles like
delhi_tech_lead_reviewer, which leads to role explosion. - over-engineered graph ABAC: you evaluate graph queries on every request, which destroys API latency.
Motherboard uses polymorphic grants with composite index lookups.
instead of duplicating foreign keys across separate user_grants and group_grants tables, the grants table links to principals polymorphically:
1class Grant(Base):
2 __tablename__ = "grants"
3 __table_args__ = (
4 # Fast composite lookup: all grants for a specific principal
5 Index("ix_grants_principal", "principal_type", "principal_id"),
6 )
7
8 id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
9 principal_type: Mapped[str] = mapped_column(String(20), nullable=False) # 'user' | 'group'
10 principal_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), nullable=False)
11 permission_key: Mapped[str] = mapped_column(String(150), ForeignKey("permissions.key", ondelete="CASCADE"), index=True)
12 resource_scope: Mapped[str | None] = mapped_column(String(255), nullable=True) # e.g. 'fork:delhi', null = global
13 expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)1. Principal Resolution & Policy Evaluation#
when a request arrives, the resolve_principal dependency resolves the user's active group memberships in a single query:
1async def resolve_principal(db: AsyncSession, user_id: uuid.UUID) -> ResolvedPrincipal:
2 user = await db.get(User, user_id)
3 if not user or not user.is_active:
4 raise HTTPException(status_code=401, detail="User deactivated or invalid")
5
6 group_ids = (
7 await db.scalars(
8 select(Membership.group_id).where(
9 Membership.user_id == user_id,
10 or_(Membership.expires_at.is_(None), Membership.expires_at > datetime.now(timezone.utc))
11 )
12 )
13 ).all()
14
15 return ResolvedPrincipal(user_id=user.id, group_ids=list(group_ids), is_super_admin=user.is_super_admin)2. The batch_can() Optimization#
evaluating permissions on a list of 50 resources (like city forks or pending signature requests) usually causes an query loop. we built batch_can to resolve permissions across arbitrary resource lists in a single SQL execution:
1async def batch_can(
2 db: AsyncSession,
3 principal: ResolvedPrincipal,
4 checks: list[tuple[str, str | None]] # [(permission_key, resource_scope), ...]
5) -> dict[tuple[str, str | None], bool]:
6 if principal.is_super_admin:
7 return {check: True for check in checks}
8
9 now = datetime.now(timezone.utc)
10 keys = {c[0] for c in checks}
11
12 principal_filter = or_(
13 and_(Grant.principal_type == "user", Grant.principal_id == principal.user_id),
14 and_(Grant.principal_type == "group", Grant.principal_id.in_(principal.group_ids)) if principal.group_ids else False
15 )
16
17 stmt = select(Grant).where(
18 principal_filter,
19 Grant.permission_key.in_(keys),
20 or_(Grant.expires_at.is_(None), Grant.expires_at > now)
21 )
22 grants = (await db.scalars(stmt)).all()
23
24 # Match in-memory: exact resource match OR global wildcard (resource_scope is None)
25 results = {}
26 for perm_key, scope in checks:
27 allowed = any(
28 g.permission_key == perm_key and (g.resource_scope is None or g.resource_scope == scope)
29 for g in grants
30 )
31 results[(perm_key, scope)] = allowed
32
33 return resultsbnb-signatures: legally binding digital signatures under Indian law#
one of the most critical systems in Motherboard is bnb-signatures—our custom digital contract execution and verification engine.
as a Section 8 non-profit company in India, our agreements with college chapters, venue sponsors, hackathon partners, and city leads cannot be casual checkboxes. they have to satisfy the Information Technology Act, 2000 and the Bharatiya Sakshya Adhiniyam, 2023 (BSA) / Section 65B of the Indian Evidence Act.
statutory validity requirements we implemented:#
- Section 10A IT Act, 2000 (Electronic Formation of Agreements): contracts formed electronically via offer, acceptance, and digital intent are legally valid and enforceable in Indian courts.
- Section 65B Evidence Act / Section 63 BSA 2023 (Forensic Tamper-Evidence): every executed contract generates an append-only cryptographic audit trail recording exact UTC timestamps, verified email addresses, signatory IP addresses, browser user-agents, and intermediate document digests.
- Class 1, 2, 3 Digital Signature Certificate (DSC) Support: support for hardware cryptographic USB tokens (ePass2003, mToken, HYP2003 via PKCS#11) and software
.pfx/.p12certificates validated against X.509 certificate chains using Python'scryptographylibrary. - Two-Stage Email OTP Challenge: automated 6-digit verification codes sent to signatory mailboxes with a 2-minute time-decay window, rate-limiting, and masked challenge display (e.g.
ak*******@g****.com).
cryptographic document sealing#
when all parties execute the document, the backend combines the signature layers, attaches a tamper-evident audit certificate, and computes a SHA-256 digest:
1def seal_document(original_pdf_bytes: bytes, overlays: list[FieldPlacement], audit_trail: list[AuditEntry]) -> tuple[bytes, str]:
2 doc = fitz.open(stream=original_pdf_bytes, filetype="pdf")
3
4 # 1. Overlay signatures, typed script text, and timestamps at precise canvas coords
5 for field in overlays:
6 page = doc[field.page_number - 1]
7 rect = fitz.Rect(field.x0, field.y0, field.x1, field.y1)
8 if field.type == "signature_image":
9 page.insert_image(rect, stream=field.image_bytes)
10 elif field.type == "text":
11 page.insert_text(rect.tl, field.value, fontsize=10, fontname="helv")
12
13 # 2. Append 1-page forensic Audit Certificate generated via ReportLab
14 cert_pdf = generate_audit_certificate_pdf(audit_trail)
15 cert_doc = fitz.open(stream=cert_pdf, filetype="pdf")
16 doc.insert_pdf(cert_doc)
17
18 # 3. Serialize and calculate immutable SHA-256 digest
19 final_bytes = doc.tobytes(deflate=True, garbage=3)
20 document_hash = hashlib.sha256(final_bytes).hexdigest()
21
22 return final_bytes, document_hashcontract assistant: deterministic rules before LLM judgment#
before a legal partnership agreement or university MOU gets dispatched for signatures, it passes through the Contract Assistant.
throwing an raw LLM at an entire contract is an easy way to hallucinate terms or miss dangerous indemnification clauses. we structured the analysis pipeline as a two-tier evaluation engine:
| Evaluation Layer | Mechanism | Purpose |
|---|---|---|
| Tier 1: Deterministic OKF Rules | 35 regex patterns & structural AST matchers | Checks mandatory Section 8 non-profit clauses (e.g. zero personal liability for student organizers, non-commercial IP retention, jurisdiction pinned to Uttar Pradesh courts). |
| Tier 2: SparkCloud LLM Risk Pass | Bounded context prompt with clause classification | Analyzes fuzzy ambiguity, non-standard penalty clauses, and unilateral termination traps. |
1class ContractAssistantFinding(Base):
2 __tablename__ = "ca_findings"
3
4 id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
5 contract_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("ca_contracts.id", ondelete="CASCADE"))
6 clause_ref: Mapped[str] = mapped_column(String(50)) # e.g., "§4.2"
7 source: Mapped[str] = mapped_column(String(50)) # "rule_engine" | "llm_judgment"
8 severity: Mapped[str] = mapped_column(String(50)) # "high" | "medium" | "low"
9 risk_type: Mapped[str] = mapped_column(String(100))
10 plain_english: Mapped[str] = mapped_column(Text)
11 suggested_action: Mapped[str] = mapped_column(Text)
12 tier: Mapped[int] = mapped_column(Integer, default=1) # 1 = Template swap, 2 = LLM redline
13 status: Mapped[str] = mapped_column(String(50), default="open")if any high severity findings remain unresolved (like an uncapped indemnification clause), the dashboard disables the "Dispatch for Signature" trigger until an executive admin either applies the suggested template fix or logs a formal justification reason.
chrono v2 & meetings: eliminating the query bottleneck#
Motherboard consolidates community scheduling, Cal.com sync, and Discord voice channel recordings into a unified system called Chrono v2.
in earlier iterations, loading the meetings index page was shockingly slow. a user with 40 scheduled meetings was taking upwards of 10.5 seconds to load.
when we profiled the SQLAlchemy query logs, we found the classic ORM disaster: for every single meeting, the system executed separate queries to fetch attendees, reschedule history records, and transcript metadata ( sequential database roundtrips).
the batch loading fix#
we rewrote the /api/meetings index router to batch-fetch all child relationships across three indexed IN queries:
1# 1. Fetch root meetings
2meetings = (await db.scalars(select(BotMeeting).order_by(BotMeeting.scheduled_time.desc()).limit(limit).offset(offset))).all()
3meeting_ids = [m.id for m in meetings]
4
5if meeting_ids:
6 # 2. Batch fetch child records in exactly 3 queries
7 attendees_res = await db.scalars(select(MeetingAttendee).where(MeetingAttendee.meeting_id.in_(meeting_ids)))
8 history_res = await db.scalars(select(MeetingRescheduleHistory).where(MeetingRescheduleHistory.meeting_id.in_(meeting_ids)))
9 transcripts_res = await db.scalars(select(MeetingTranscript).where(MeetingTranscript.meeting_id.in_(meeting_ids)))
10
11 # 3. Map into memory dictionaries
12 attendee_map = defaultdict(list)
13 for a in attendees_res: attendee_map[a.meeting_id].append(a)
14 history_map = defaultdict(list)
15 for h in history_res: history_map[h.meeting_id].append(h)
16 transcript_map = {t.meeting_id: t for t in transcripts_res}| Metric | Legacy ORM Fetch | Chrono v2 Batch Fetch | Improvement |
|---|---|---|---|
| SQL Queries / Page | (121 queries for ) | 4 fixed queries | 96.7% fewer queries |
| p95 API Latency | 10,420ms | 42ms | 99.6% faster |
| DB CPU Load | 78% during meeting spikes | < 3% | Massive compute savings |
native RFC-2446 email calendar RSVPs#
when scheduling a community sync or council review, sending a plain text email means users forget to manually create a calendar event.
we updated Motherboard's mailer to construct multipart/mixed MIME messages containing an inline text/calendar; method=REQUEST payload with deduplicated ORGANIZER and ATTENDEE tags. when Gmail, Apple Mail, or Outlook receives the email, it renders the interactive "Yes / Maybe / No" RSVP buttons natively inside the inbox header.
Content-Type: multipart/alternative; boundary="boundary-alternative"
--boundary-alternative
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: 7bit
<h2>Your bits&bytes sync has been scheduled</h2>
...
--boundary-alternative
Content-Type: text/calendar; charset="utf-8"; method=REQUEST
Content-Transfer-Encoding: 7bit
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//bits&bytes//Motherboard Chrono//EN
METHOD:REQUEST
BEGIN:VEVENT
UID:meet-9f8e7d6c5b4a@gobitsnbytes.org
DTSTART:20260825T140000Z
DTEND:20260825T144500Z
SUMMARY:Delhi City Fork Tech Sync
ORGANIZER;CN=Akshat Kushwaha:mailto:akshat@gobitsnbytes.org
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:guest@example.com
END:VEVENT
END:VCALENDAR
--boundary-alternative--paper finance: integer paise and floating-point discipline#
managing hackathon logistics and reimbursement requests across cities requires paper ledger tracking before routing through bank current accounts.
a common trap is using floating-point types (Float or Double) for financial balances. in IEEE 754 floating-point representation:
over thousands of micro-transactions, floating-point rounding errors accumulate and create reconciliation mismatches.
Motherboard stores all financial values strictly in integer paise ():
1class VirtualAccount(Base):
2 __tablename__ = "virtual_accounts"
3
4 id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
5 owner_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), index=True)
6 name: Mapped[str] = mapped_column(String(100), nullable=False)
7 balance_paise: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
8 account_number: Mapped[str] = mapped_column(String(20), unique=True, index=True)
9 ifsc: Mapped[str] = mapped_column(String(11), default="GOBN0001001", nullable=False)every transaction creates a balanced, immutable VirtualTransaction entry linking debits and credits, allowing instantaneous mathematical auditing.
lived scar tissue: when the managed database ran out of compute#
writing about architecture is easy when you only describe the happy path. the reality of building Motherboard involved real operational emergencies.
in early August 2026, during a peak onboarding surge for new city chapters, our server logs suddenly lit up with HTTP 500 errors on POST /api/auth/upsert.
when we inspected journalctl on the VPS, we found:
asyncpg.exceptions.InsufficientResourcesError: remaining connection slots are reserved for non-replication superuser connectionsour managed cloud PostgreSQL tier (Neon) had exceeded its active compute and connection quotas during background Discord member synchronization. because the API depended synchronously on this external database, authentication and dashboard navigation ground to a halt.
the recovery#
we didn't wait for cloud support tickets:
- provisioned a local, persistent Docker container
bnb-postgresrunningpostgres:16-alpineon our primary VPS with dedicated SSD volume mounts. - updated the API connection pool configs (
pool_size=20,max_overflow=10,pool_pre_ping=True). - executed Alembic migrations (
alembic upgrade head) and ran the seed scripts to restore all 15 system groups, 23 core permissions, and city fork mappings. - added an automated database backup cron generating encrypted daily
.sql.gzsnapshots to external object storage.
within 45 minutes, services were restored to 100% green health.
knowing when to build vs when to integrate#
a major trap for software builders is the urge to reinvent everything.
in Session 53, as our community scaled, we asked ourselves an honest question: should we spend the next six months building our own webmail client, document collaboration editor, and video calling infra inside Motherboard?
the answer was an emphatic no.
we integrated a self-hosted Nextcloud Hub workspace (workspace.gobitsnbytes.org) backed by 5TB of high-speed NVMe storage, Nextcloud Talk for video calls, and an automated background mail provisioner (bnb_auto_mail_provisioner.py) that provisions @gobitsnbytes.org mailboxes on our Indian mail servers when contributors complete their team profile.
Motherboard retained the things it does better than generic software:
- our custom Polymorphic IAM and Discord Guild Role Mapper
- our statutory Digital Signatures Engine (
bnb-signatures) - our Contract Assistant and Section 8 Governance Rules
- our Chrono v2 Meeting Scheduler
systems shouldn't be built to satisfy architectural vanity. they should be built to remove friction from the people doing the work.
what holds up#
building Motherboard taught me that operational platforms aren't defined by how clean their initial schema looks on a whiteboard. they are defined by how they behave when:
- an external API changes its schema at 2 AM
- an urgent contract needs to be executed on mobile by a signatory with spotty 4G
- forty people try to schedule meetings at the same minute
- a volunteer needs to verify that an agreement hasn't been tampered with
you don't need a team of twenty engineers to build reliable, production-grade infrastructure. you just need to respect data consistency, measure your query latencies, handle failure modes explicitly, and write software that treats its users' time with respect.
Motherboard is running in production today across the bits&bytes network at gobitsnbytes.org.
drafted with an LLM, then reviewed and edited by me before it went up.
0 responses
leave something useful, or usefully sharp.