my-approval · v0.1 upgrade
DRAFT
Spec for the dev team 2026-05-17
⬡ in-place upgrade · existing swiftrise-my-approval repos

Approvals that finish. Not approvals that drift.

An upgrade to the existing swiftrise-my-approval-* repos that turns it into the management team's document approval system across MPA Group entities. Same codebase, new capabilities: document typology, EXTERNAL routing, multi-signer light eSign, paper-trail awareness, audit-locked.

Audience
Management only
Entities
7 + Runa sites
Timeline
~5 weeks · M0–M4
Stack
Nest · React/Vite · Postgres
Design
Follows mandala UI
Build by
BE engineer · FE engineer
Executive summary

What this is.

An in-place evolution of the existing swiftrise-my-approval app into the cross-entity document approval system for the management team. v0.1 covers in-app + email/Teams notifications. WhatsApp, PSrE eSign and DocGen sync land in v2.

Approach
In placebranch in existing repos, not a fork
Reuse
~60%of workflow plumbing already exists
Channels
Web + email + TeamsWhatsApp = v2
DB change
MySQL → Postgres+ multi-tenant on existing tables
Doc types
13 seededPolicy · WI · SOP · Form · Memo · Agreement · Contract · MOU · Resolution · SE · Circular · JD · Other
Sign methods
4None · Light eSign · Wet ink · Provider
Evidence captured
7 fieldsemail · IP · UA · ts · image · doc URL · hash
Two artifacts
Source + Proofsource PDF untouched · system generates a separate proof certificate
Why now

Three failures the current paper form keeps producing.

PROBLEM 01

Numbering drift.

11 published Surat Edaran already have anomalies: 01 / 03 duplicated, 04 year typo, 09 unnumbered. No register, every issuance is hand-checked.

PROBLEM 02

Silent paper.

Approvers receive paper, take it home, return it days later. Nobody knows where the doc is. Wet-ink takes a week with zero visibility.

PROBLEM 03

Indistinguishable contracts.

An NDA to a regulator and an internal JD use the same form, same routing, same defaults. Nothing flags EXTERNAL for legal review or SLA.

In-place upgrade, not a fork

Work lands in existing repos on a feature branch.

No new repos. No "DocApprove" sibling app. The dev team creates feat/v0.1-doc-upgrade on both swiftrise-my-approval-api-nest and swiftrise-my-approval-dashboard-react, lands all the changes there, then merges to main when QA passes.

Keepalready in repo
request request-approval request-file request-approval-file audit-log temp-file S3Service RbacService
Dropreplace with matrix
RequestApprovalTemplate (single fixed approver)
Addnew entities
tenants document_types departments approval_matrix request_signatures user_signatures paper_signing_log
Extendadd columns
requests + tenant_id, type_id, dept, scope, urgency, dates, signing_method RequestStatusEnum 4 → 7 values
Status enum

Four current states → seven, mirroring the paper form's three decisions.

The paper form has three decision boxes: Disetujui, Disetujui dengan perubahan, Ditolak. The current code only models two of those, plus a generic "Submitted". We expand the enum so semantics map cleanly.

APPROVED
"Disetujui" — clean approval. Effective on approved_at or effective_date.
APPROVED_WITH_CHANGES
"Disetujui dengan perubahan" — final approver noted edits. No new cycle.
CHANGES_REQUESTED
Reviewer sends back. Creator revises, version++ creates fresh approval chain.
REJECTED
"Ditolak" — chain stops. Creator may submit a new document, not a new version.
Paper form to schema

Every field on the rev2 paper form, mapped to a column.

Devs read this row by row. Nothing the paper form does is lost. Existing columns reused where they fit.

Paper field
Digital field
Status
Header "INTERNAL DOCUMENT USE ONLY"
recipient_scope = INTERNAL
Kept
Jenis Dokumen ☐ Policy / WI / Form / Memo / Agreement
document_types.code
New
Jenis Dokumen ☐ HC / Finance / Legal / Operational
departments.code (split)
Split
Jenis Dokumen ☐ Lainnya
document_types.code = OTHER + type_other_label
New
Departemen / Fungsi
requests.department_code
New
Yang Mengajukan
requests.created_by (existing)
Kept
Tanggal diajukan
requests.submitted_at (existing)
Kept
Tanggal Target Final
requests.target_finalization_date
New
Tujuan / Ringkasan
requests.description (existing)
Kept
Keputusan ☐ Disetujui
status = APPROVED (existing)
Kept
Keputusan ☐ Disetujui dengan perubahan
status = APPROVED_WITH_CHANGES
New
Keputusan ☐ Ditolak
status = REJECTED (existing)
Kept
Tanggal berlaku
requests.effective_date
New
Tanggal review
requests.next_review_date
New
Note (final approver)
final request_approvals.reason (existing)
Kept
Dibuat / Direview / Disetujui oleh blocks
request_signatures with role mapping
New
(none)
recipient_scope = EXTERNAL + external_party
New
(none)
tenant_id on all rows
New
Mobile-first prototype

Built for the phone first, using the existing mandala design.

Uses the SwiftRise design system already in swiftrise-mandala-dashboard-react — Inter font, accent green #12664E, shadcn-style border-and-radius primitives, Heroicons. No new components invented. Layout copies MainLayout.tsx (sidebar drawer + topnav on mobile, fixed sidebar on lg).

01Inbox · what is waiting on me
02Document detail with ApprovalProgressBar
03Preview · source PDF (untouched)
04Decide · approve / with changes / reject
05Sign · light eSign canvas + evidence
06Approval proof · the generated artifact
07Create new · classify + route
08Paper custody · wet-ink trail
09Dashboard · my docs in flight
10Revisions · file version history
11Time analytics · cycle times + bottlenecks

Eleven screens cover the full submitter and approver journey on mobile. Each component reuses something already in the mandala repo: ApprovalProgressBar for chain visualization, ActivityInfoCard for created/signed metadata, Button with the primary variant for CTAs, InfoSection for grouped fields.

The mandala visit-approval page is the closest structural reference. the dev team should start there.

Note the time strip on screen 02 (Detail) and the dedicated Insights screen (11) — both surfaces of the same data: request_approvals.activated_at and actioned_at. Cycle time is a first-class concept, not buried.

Two artifacts, never confused. Screen 03 (Preview) shows the source PDF the submitter uploaded, never modified by the system. Screen 06 (Proof) shows the system-generated approval proof PDF — a separate file that references the source, lists the chain, and embeds the signatures. The proof is the audit artifact.

09:41● ● ●
Inbox
3 awaiting you
JE
For me All MPA All entities Sent
Awaiting decision2
NDA · PT Sample Counterparty 2d
MPA-CA-AGR-2026-0117 · from Henry
ExternalUrgentAgreement
Revisi JD Vice GOM 8h
MPA-HC-JD-2026-0042 · from Anne
JD
Awaiting signature1
SE Kebijakan Kredit Customer 1d
MPA-FCT-SE-2026-0012 · approved · 3 signers
Light eSign
Drafts1
SOP Asset Custody Handover v2 3d
not submitted
Draft
Inbox
Mine
New
You
09:42● ● ●
Document
v1
MPA-CA-AGR-2026-0117
NDA · PT Sample Counterparty
External Urgent Agreement
Approval progress
Anne
Legal
3
You
Purpose
NDA covering preliminary discussions on a JV for forestry-segment parts distribution. Counterparty has requested a 30 day return on signed.
Details
DepartmentCorporate Affairs
SubmitterHenry H.
CounterpartyPT Sample Counterparty
Target final15 Jun 2026
Effective dateupon signing
Time on each step
3d
1d
2d
SLA
Anne · Doc Control3d 4h
Legal Reviewer · auto-injected22h
You · pending2d 1h
Total elapsed: 6d 3h Target: 9d
Attached files
LatestNDA-sample-cpty-v3.pdf
Revisions3 versions → tap to see history
09:42● ● ●
NDA-sample-cpty-v3.pdf
1 / 4
NDA-v3.pdf due-diligence.pdf cv-perusahaan.pdf

Non-Disclosure Agreement

Between PT Multi Power Aditama & PT Sample Counterparty
Version 3 · Revised 15 May 2026
Effectiveupon signing
Term24 months
Governing lawRepublic of Indonesia

1. Purpose

This Agreement governs the exchange of confidential information between the Parties in connection with preliminary discussions regarding a potential joint venture covering distribution of undercarriage parts to the forestry segment in Indonesia.

2. Confidential Information

"Confidential Information" means any non-public information disclosed by either Party in any form, including pricing, supplier lists, technical specifications, and customer data.

3. Obligations

  1. Each Party shall keep all Confidential Information strictly confidential.
  2. Disclosure to employees is permitted on a need-to-know basis and subject to equivalent obligations.
  3. Reverse engineering of disclosed materials is prohibited.

4. Term

This Agreement remains in force for twenty-four (24) months from the Effective Date, after which obligations of confidentiality survive for an additional thirty-six (36) months.

7. ~~Non-Solicitation~~

Neither Party shall solicit the employees of the other for a period of twelve (12) months from termination.

Clause struck per Legal Reviewer note 14 May. See revision log.

PT Multi Power Aditama
PT Sample Counterparty
v2 · annotations Tap any text to highlight, comment, or redline. Anchored to this revision.
09:43● ● ●
Approve with changes
MPA-CA-AGR-2026-0117
Conditions on approval
Updated dates
Effective dateupon counter-signing
Review date15 Jun 2027
Notify Henry by email + Teamssend conditions to submitter
Auto-watermark on releaseEXTERNAL doc, on by default
09:44● ● ●
Sign · slot 2 of 3
SE Kebijakan Kredit Customer
Your signature
Clear Use saved signature
What gets recorded
Signed by: director@example.com
Timestamp: 2026-05-17 09:44 +08
IP: 103.14.xx.xx
Agent: iPhone 15 · Safari · iOS 19.2
Image: stored S3 / sg region · hashed
Evidence: sha256:af3d…c91

Light eSign is defensible internally. Not PSrE-binding. For court-enforceable contracts use PrivyID or Mekari (planned for v2).

09:48● ● ●
proof-MPA-CA-AGR-2026-0117.pdf
FINAL
PT Multi Power Aditama

FORM APPROVAL / Bukti Persetujuan

FINAL · EXTERNAL
Verify: docapprove.jofnd.ai/v/9X3F-K2QD
Source document
NDA-sample-cpty-v3.pdf · 4 pages · 142 KB
sha256: 7b4d2f8a…e91 · uploaded 15 May 2026 by Henry
Revision 3 of 3 · is_current=true

Informasi Pengajuan

Jenis: Agreement / Legal
Departemen: Corporate Affairs
Pengaju: Henry H.
Counterparty: PT Sample Counterparty
Tgl diajukan: 10 May 2026
Target final: 15 Jun 2026

Tujuan / Ringkasan

NDA for preliminary JV discussions on forestry-segment parts distribution. 24-month confidentiality, governing law RI.

Approval chain

1Anne · Doc ControlDisetujui2d
2Legal Reviewer · auto-inj.Disetujui1d
3Director (you) · Holding OwnerDisetujui dgn perubahan2d

Keputusan

Disetujui dengan perubahan. Tgl berlaku: upon counter-signing. Tgl review: 15 Jun 2027.

"Approved subject to: (1) Section 4 confidentiality term to 24 months, (2) Section 7 non-solicit struck, (3) Annex A with subsidiary list included at signing."

Signatures

~ Henry ~ Dibuat oleh
Henry H.
coo@example.com
10 May · light eSign
~ Anne ~ Direview oleh
Anne (Doc Ctrl)
doc-control@example.com
12 May · light eSign
~ Joseph ~ Disetujui oleh
Director (you)
director@example.com
17 May · light eSign
Generated by my-approval on 2026-05-17 · Proof hash sha256:c3f8…2b4a · Source NDA-sample-cpty-v3.pdf unchanged
09:45● ● ●
New document
Step 1 of 3 · classify
Policy SOP Memo Form Agreement Contract SE JD Other
HC Finance Legal Operations Corp Affairs QMS IT
Drop a PDF here, or tap to select
PDF only · max 25 MB · export from Word/Pages first if needed
External recipientauto-sets urgent + important + injects legal review step
09:46● ● ●
Paper trail
Board Resolution 2026-08
Custody now
Holding since 2d
Anne · Doc Control
Cabinet B-3 · Floor 3
Movements
Printed and assigned
15 May · MPA-LGL-RES-2026-0008
15/05
Signed · Joseph
slot 1 · CEO
15/05
Signed · Henry
slot 2 · COO
16/05
In custody · Anne
scanning + archiving
today
4
Archive
long-term · legal cabinet F3
pending
Scan upload
09:48● ● ●
File revisions
NDA · Sample Counterparty
Revision chain
3 versions of the source document. Each revision is linked to the prior one via supersedes_file_id and tagged with a note.
v3
NDA-sample-cpty-v3.pdf 2d ago
"Annex A added with subsidiary list per Joseph's note."
Current Henry · 142 KB
v2
NDA-sample-cpty-v2.pdf 5d ago
"Struck §7 non-solicit clause per Legal Reviewer feedback. §4 term reduced 36mo → 24mo."
Superseded by v3 Henry · 138 KB
v1
NDA-sample-cpty-v1.pdf 7d ago
"Initial draft."
Superseded by v2 Henry · 134 KB
Supporting docs (unchanged)
counterparty-due-diligence.pdf · 14d ago
sample-cpty-cv-perusahaan.pdf · 14d ago
09:49● ● ●
Time analytics
this quarter
JE
2.8davg
My cycle time
−18%vs Q1
Trend
14hmedian
My decision time
2breached
SLA misses
Slowest in-flight (right now)
Sorted by current step wait time
Vendor SOP v3
5d 8h
Cabin Allowance Pol.
3d 1h
NDA Sample Cpty
2d 1h
SE Kebijakan Kredit
1d
Doc type benchmarks
Avg cycle time across all entities
Type
You
Org p50
Org p90
Contract
5d
7d
14d
SOP
8d
4d
9d
JD
2d
3d
6d
SE
4d
5d
11d
Memo
1d
2d
4d
Avg decision time, by approver
Across all docs they touched · sorted by speed
Anne
6h
Yusuf
14h
You
18h
Henry
1d 5h
Legal
1d 18h
CEO
2d 14h
Inbox
Mine
New
Insights
09:47● ● ●
My documents
this quarter
JE
12approved
Done this Q
3in flight
Awaiting
1.4davg
Time to approve
0rejected
This quarter
In flight3
SE Kebijakan Kredit Customer2/3 signed
signature phase
Sign
Vendor Onboarding SOP v32/4 steps
Anne pending
Review
Cabin Allowance Policy1/3 steps
Yusuf pending
Review
Inbox
Mine
New
You
Desktop · always-on preview

Same app, split-pane at lg: breakpoint up.

Desktop puts the preview on the right and keeps it visible while the approver reads the metadata, scans the chain, and decides on the left. Same React code as mobile; the layout collapses to single-column under 1024px. Three columns: mandala sidebar, document detail, always-on preview pane.

my-approval.jofnd.ai/d/MPA-CA-AGR-2026-0117
Inbox MPA-CA-AGR-2026-0117 · v1

NDA · PT Sample Counterparty

External Urgent Agreement Awaits sign 2/3
Approval progress
Anne
Legal
3
You
Tujuan / Ringkasan

NDA covering preliminary JV discussions for forestry-segment parts distribution. 24-month confidentiality, counterparty requested 30-day return on signed.

Details
DepartmentCorporate Affairs SubmitterHenry H. CounterpartyPT Sample Counterparty Target final15 Jun 2026 Effectiveupon signing Review dateauto +12 mo
Time on each step
3d 4h
22h
2d 1h
SLA buffer
Anne · approved3d 4h
Legal Reviewer · approved22h
You · pending2d 1h
Elapsed: 6d 3hTarget: 9d
Attached files
NDA-sample-cpty-v3.pdf Current · v3
due-diligence.pdf Support
cv-perusahaan.pdf Support
View revision history (3 versions) →
Why split-pane on desktop

Approvers stop scrolling between metadata and the document itself. The preview is always visible while they read the chain, check timing, and click Approve. Removes the cognitive cost of context-switching.

Same code, responsive collapse

Under lg: (1024px), the preview pane collapses to a tab in the detail screen — mobile flow takes over. Above it, the three-column layout activates. No separate desktop build.

Source / Proof tab in preview pane

The preview tab strip ends with a Proof tab. While the request is still in review it shows "Proof (pending)". On APPROVED it activates and renders the generated proof PDF in the same pane. One surface, two artifacts.

Roadmap

v0.1 in five weeks. Five milestones.

M0 is the in-place foundation: Postgres + multi-tenant + management gate on existing repos. M2 is the highest-risk milestone (signature evidence).

M0
Foundation in place
Branch feat/v0.1-doc-upgrade on both repos. MySQL → Postgres migration, multi-tenant middleware on existing request_* tables, management-only RBAC gate.
Week 1
M1
Types, matrix, revisions, time fields
Seed document_types + departments, replace RequestApprovalTemplate with approval_matrix, add new columns to requests, add revision columns to request_files, add activated_at + sla_hours to request_approvals, EXTERNAL side effects.
Week 2
M2
eSign, revisions, preview, proof PDF
Add request_signatures + user_signatures + request_approval_proofs, mobile signature canvas, per-signer evidence capture, revision history view, PDF.js inline preview, generate the approval proof PDF (provisional on APPROVED, finalized on full-signed) with verify link.
Week 3
M3
Paper custody + SharePoint export + time strip
Add paper_signing_log, custody UI, WET_INK flow, one-way export of approved PDFs to SharePoint, time strip on document detail (per-step elapsed).
Week 4
M4
Insights dashboard + notifications + UAT
request_metrics_cache denormalized view, Insights screen (bottlenecks + benchmarks + per-approver speed), Teams Adaptive Cards, email via Graph, cross-entity inbox, SLA cron, Codex review, UAT with one sitting director.
Week 5
v2 roadmap

Deferred to v2.

v0.1 ships an in-app + email/Teams approvals system. v2 expands channels and provider integrations. WhatsApp is the most-requested v2 item.

v2
WhatsApp Business API channel

Meta-direct, not BSP. Templated assignment messages with Approve / Reject / View buttons. Reason captured by reply. Deep-link to app for signing. Fallback to Teams + email if WA delivery fails. Templates take 1–3 days each to clear Meta review.

v2
Multi-format uploads (DOCX, XLSX, PPTX, images)

v0.1 accepts PDF only. v2 adds server-side conversion via LibreOffice headless or Gotenberg, plus the columns to track conversion state (preview_status, preview_error). Submitters export to PDF themselves until then.

v2
PDF annotations on preview

Highlights, sticky comments anchored to coordinates, redlines, freehand markup. Annotations attach to a specific revision so they do not drift when a new version is uploaded. Unresolved annotations block approval; resolved ones grey out. Storage: request_file_annotations with author, kind, page, coords, body, resolved-by.

v2
PSrE eSign provider

PrivyID or Mekari Sign for court-binding signatures under UU ITE. Trigger only for signing_method=PROVIDER_ESIGN. ~Rp 20–50k per signature.

v2
SharePoint inbound sync

v0.1 ships export only. v2 adds: drop a draft into a watched SharePoint folder, DocApprove auto-creates the request.

v2
DocGen integration

Wire swiftrise-docgen-api-nest directly into request creation. Generate SOP / JD / SE draft from structured input, skip the upload step.

Dev handoff

Built by SwiftRise, in-place, on a feature branch.

A BE engineer takes the backend. An FE engineer takes the frontend.

Joseph signs off, work lands on feat/v0.1-doc-upgrade on both my-approval repos, merges to main when QA + UAT pass. Codex reviews before deploy. Org-visible actions wait for go-ahead.

Spec MDdocapprove-v0.1.md
Spec HTMLdocapprove-v0.1.html
API reposwiftriseio/swiftrise-my-approval-api-nest
FE reposwiftriseio/swiftrise-my-approval-dashboard-react
Branchfeat/v0.1-doc-upgrade
Referencemandala/visit-approval page
Designfollow mandala tokens + components
Patternsprocure-system (matrix) · sentinel-cab (tenants)
ReviewerCodex + Lead engineer
UATOne sitting director, real document