Chuyển tới nội dung chính

Signet

Signet — Open-source e-Office, self-hosted, your data, your control

🇻🇳 Tiếng Việt | 🇬🇧 English

A self-hosted, open-source core platform that puts a seal of trust on everything that passes through it — with its first application on top: an e-Office for incoming and outgoing official documents under Vietnam's Decree 30/2020/NĐ-CP on clerical work.

License: Apache 2.0 CI Release

Built for the Vietnam Student Olympiad in Informatics 2026 — Open Source Software track (OLP PMNM 2026), theme DX-OS Open-Core. Most project documentation is written in Vietnamese; this page is a translation of README.md.

Try it: https://signet.htechcs.com (latest release plus a few fixes, see Try it out) · or install it on your own machine with four commands from Building from source.

Five-minute tour and documentation map (in Vietnamese): docs/README.md · documentation site https://hit-champion.github.io/Signet/.

Quick links: Introduction · Architecture · Features · Four principles · Technology · Install · Try it out · Operations · Troubleshooting · Documentation · Contact · License


Introduction​

A signet is the ring once pressed into wax to seal letters and documents: the seal tells you who sent it, and an unbroken seal tells you nobody opened or altered it. The Signet core does the same for digital data.

More than 900,000 small and medium enterprises, together with schools, faculties and grassroots agencies, digitalise by buying many separate tools (the data turns into silos) or one monolithic system (the organisation becomes a "hostage" of one vendor and loses its digital sovereignty). Either way, every new application rebuilds sign-in, file storage, permissions and approval workflows from scratch — and has to take care of trust on its own, which it usually does not.

Signet splits that shared part into a headless core running in the background, assembled entirely from open-source software so the organisation can install and own it. A new application only plugs into the core and gets four seals of trust out of the box, without building them itself:

SealMeaningComponentsTier 1 cluster
Known authorEvery call carries an SSO identity, AI agents included; privileged roles must use two-factor authenticationKeycloak, APISIX① ②
CleanFiles are scanned for malware before they are stored; infected files never reach storagesvc-files + ClamAV①
Tamper-evidentEvery change goes into a hash-chained audit log; the chain's anchor lives outside the database, and make audit points at the altered rowPostgreSQL, schema core⑥
Verifiable from outsideIssued documents carry a QR code, a SHA-256 hash and a digital signature (illustrative only, no legal validity); the public verification portal needs no loginsvc-files, route /api/verify④ ⑥

Architecture​

Architecture diagram: users go through the APISIX gateway to the four H-P-D-I spaces of Tier 2 and the Tier 1 core
services; the right column holds the outside notification channels: email, webhooks, SMS,
Zalo

Signet follows the three tiers of the DX-OS brief:

  • Tier 1, the headless core: identity, API gateway, structured and unstructured data, workflow, the trust layer (the seven clusters ①–⑦, docs/architecture.md section 3, Vietnamese). It has no business screens; applications reach it through the gateway.
  • Tier 2, the four H-P-D-I spaces with a user interface (table below). The e-Office is one web application with screens in all four spaces; its server side still runs in the same process as the core services (boundary and the way out: docs/architecture.md section 4). The P.A.R.A personal space changes no core service code, but it was added by hand to the core configuration (a Keycloak client, a gateway route, tables and permissions in the database). The unit news board and the leave request app plug in with one moc app install command without changing any core file (docs/them-ung-dung.md, Vietnamese).
  • Tier 3, industry applications (sales, warehouse, learning, customer relations…): optional in the brief. The first one is the teaching schedule change app (apps/lich-giang): a lecturer asks, the head of department and then the unit director approve on the core workflow engine; it plugs in like the news board, with moc app install.
SpaceTier 2 screens and applications
[H] HumanP.A.R.A personal space (each person's files), unit news board, the e-Office Apps page; DokuWiki wiki (wiki profile). Single sign-on, roles and units come from Keycloak in Tier 1
[P] Processe-Office: intake, incoming and outgoing documents, task inbox and deadline calendar, registers; leave requests; the form builder for administrators
[D] Datae-Office: executive dashboard, metrics, data lineage, sensor map, audit log, case files (archiving to cold storage, reading room), the status page with the age of the two public data sources (/trang-thai); the API docs page (REST, GraphQL)
[I] Intelligencee-Office: full-text search, Q&A (keyword and semantic retrieval), field suggestions when taking in an incoming document, assignment suggestions

Only the APISIX gateway is exposed, and every request passes its web application firewall before it reaches the core; the labels on its arrows are the real paths. The same holds inside the machine:

  • application containers sit on their own Docker network, apps (no Internet access), where APISIX is the only core service;
  • so an application's server side also reaches the core through the gateway, with the same token check, rate limits and WAF as a browser;
  • make demo-cai-ung-dung checks that the container reaches APISIX only (docs/them-ung-dung.md section 1.4, Vietnamese).

Thick borders mark the team's own code, boxes with a logo are upstream open source used as is, and the moving dots follow two real requests. H-P-D-I architecture and technical decisions: docs/architecture.md (Vietnamese).

Features​

e-Office​

In faculties, schools and small agencies, official letters still arrive on paper or as scans sent over email and chat apps; the clerk logs them in a notebook or a spreadsheet; managers write instructions on paper. On Signet, an official letter goes through its whole life cycle receive → register → instruct → handle → reply → issue → archive following Decree 30/2020/NĐ-CP on clerical work:

Problem todayHow Signet handles itSpace
Documents get lost; nobody knows whose desk they are onRegistration, a BPMN workflow, the right person's task inbox, instant notifications[P]
Deadlines pass with no reminderA deadline per assignment, automatic reminders, then escalation to managers; urgent documents go to the top[P]
Typos and duplicate registrationsWrong input is blocked in the form, on the server and in the database by one shared JSON Schema (poka-yoke); duplicates are refused[P]
Clerks retype every incoming letterAn agent reads the PDF text layer or OCRs the scan and suggests the number, date, issuing body and summary[I]
Units send documents to each other by emailIn-system exchange on the same installation: the recipient gets an incoming document at once, byte-identical file, with a verification code[P]
Sensitive documents leakPer-file encryption, decrypted only in memory for named readers; every opened page is stamped with the viewer's name[P]
Managers cannot see where work is stuckAn executive dashboard built on real data[D]
Finding old documents takes timeFull-text search, including text inside attached PDFs and scans (OCR); a Q&A assistant answers with document number and page[I]

Also: incoming and outgoing registers in the Decree 30 format; several units on one installation, each person seeing only their own unit's data; the e-Office interface in Vietnamese and English. Scope and roles: docs/dac-ta-san-pham.md; maturity of each feature with its evidence: docs/muc-hoan-thien.md (both in Vietnamese).

P.A.R.A personal space​

Each person's files in four folders — Projects · Areas · Resources · Archives; its own Keycloak client, calling the core through the gateway like any application, without changing core service code; its tables, permissions, client and route were added by hand to the core configuration (make demo-ca-nhan).

Plugging in an application with one command​

python3 scripts/moc.py app install apps/bang-tin/app.yaml reads the application's manifest and creates its Keycloak client, APISIX route, container, schema and migrations run under the application's own database role (with no rights on the core), Hasura tables and permissions, and a subscription to the core's document events. No core file changes. Running it again creates nothing twice; moc app remove uninstalls the application and keeps its data. The sample application is the unit news board (apps/bang-tin, /bang-tin/): documents just registered or issued appear as the core's events arrive, and each person only sees items for documents they may read (make demo-cai-ung-dung). How it works, the trust model and limits: docs/them-ung-dung.md section 1 (Vietnamese).

Local AI assistants​

AI in Signet only suggests; people decide. By default everything runs on the organisation's own server and no data is sent out.

AgentWhat it does
Reading incoming lettersReads the PDF text layer, or recognises the text (Vietnamese Tesseract) for photos and scans, and suggests values for the six fields of the intake form with a confidence score. Numbers and dates are always decided by rules following the Decree 30 format, never by a model. On 22 sample documents: document number correct 20/22, issue date correct 22/22
Q&A over the document storeAsk in everyday language and get verbatim quotes with the source "number · p. n"; only searches documents the asker may read, and restricted documents never enter the index
Assignment suggestionsWhen a document is registered, suggests the lead unit and the deadline, with similar past assignments as evidence; runs in parallel and never blocks the manager
Personal data maskingNational ID numbers, phone numbers, emails and bank accounts are masked before they reach a model or the logs; people allowed to read the document still see the real numbers

All four work without a language model, so they run in CI, on weak machines and offline. A local model (Ollama, Qwen3 1.7B, on CPU) writes summaries and answers: make ai-model, then make up-ai. The answer-writing step alone can call an external OpenAI-compatible API instead of Ollama (MOC_ASK_API=openai, off by default, #430); when it is on, the question and up to 4 supporting passages leave the server with ID card numbers, phone numbers, email addresses and bank account numbers masked; names and addresses are not masked. Embedding (semantic search) can move to an external API too (MOC_EMBED_API=openai, off by default, #498); when it is on, every non-restricted passage in the index, masked the same way, leaves the server. Measurements and limitations of each agent (Vietnamese): docs/danh-gia-ai.md.

Screenshots​

Taken automatically during the e2e run (make e2e), with fictional sample data. The interface is in Vietnamese by default; every page of the e-Office, the P.A.R.A personal space, the unit news board and the leave request app also has an English version.

The clerk uploads an incoming letter, the agent pre-fills the fieldsManagers see where work is stuckRecipients verify a document without signing in
Receiving an incoming document with suggested fieldsManagement dashboardPublic document verification portal

Evidence for the four design principles​

Each design principle of the contest has a demo run by one command, under a minute, printing every step with a ✓, repeatable any number of times — the presentation script is docs/demo-script.md.

PrincipleDemoCommand
(i) Data life cycle and velocityA closed file is archived as a Parquet package + files + hashed manifest in write-locked cold storage; still searchable, and scanning the QR code still says "match"; in the UI: build case files, department heads archive, the reading room shows files stamped with the viewer's name; the director's dashboard counts archived documents with DuckDB straight from the Parquet packages in cold storagemake demo-nong-lanh
(ii) IT/OT convergenceTemperature sensor → NGSI-LD (Scorpio) → above the threshold, a draft "incident report" enters the outgoing document workflowmake demo-it-ot
(iii) Data governanceOpenLineage provenance: the archive package traces back to the business tables and original files; row counts and required columns checked before writing; every Overview chart traces back to its view and source tables (computed from the PostgreSQL catalog), shown as a graph on the Data lineage page (/pha-he)make demo-pha-he
(iv) Zero-TrustMalware screening: svc-files scans every file with ClamAV before storing it; an EICAR file is refused, not stored, and the refusal is written to the audit logmake demo-kiem-dich
(iv) Zero-TrustRestricted documents: files encrypted in storage, only named people can open them, opened copies carry the viewer's namemake demo-han-che
(iv) Zero-TrustSecrets vault: svc-files and svc-workflow read their secrets from OpenBao (AppRole), not from environment variables; the vault unseals itself on restartmake demo-ket-bi-mat
(iv) GitOpsSelf-healing: delete a container and the reconciler rebuilds it from what git declaresmake demo-tu-phuc-hoi

Business demos, run the same way: make demo-lien-thong (exchange between two units), make demo-nap-lo (batch import of incoming documents), make demo-doc-van-ban, make demo-hoi-dap, make demo-giao-viec, make demo-che-pii (AI assistants), make demo-ky-so (digital signature, illustrative), make demo-ca-nhan (a second application on the same core), make demo-cai-ung-dung (plugging in a third application with one command), make demo-quy-trinh (a fourth application that brings its own process and runs it on the core's workflow engine), make demo-tat-van-phong (turning off the e-Office part, the core keeps running), make demo-log-tap-trung (centralised logs).

Technology and licenses​

Signet orchestrates open-source software in its original form: official images, pinned versions, no upstream code modified. The full table (version, license, homepage): COPYRIGHT.txt; the reasons for each choice: DEPENDENCIES.md.

SpaceComponentVersionLicenseRole in Signet
GatewayApache APISIX3.18.0Apache-2.0The only exposed entry point: JWT check at the edge, path allow-list, rate limits
GatewayCoraza, OWASP CRS (coraza-proxy-wasm)3.3.3, 4.14.0 (0.6.0)Apache-2.0Web application firewall inside APISIX: inspects every request before the token check, attack payloads get 403
[H]Keycloak26.7.5Apache-2.0Single sign-on, TOTP; roles, unit and department go into the token
[H]DokuWiki2026-07-14cGPL-2.0Internal wiki, one space per unit, sign-in through Keycloak, optional (profile wiki)
[P]Flowable8.0.0Apache-2.0BPMN workflows for incoming and outgoing documents
[P]Centrifugo6.9.7Apache-2.0Instant notifications over WebSocket, one channel per person
[P]Node-RED5.0.8Apache-2.0Automation with flows that call the core through a unit's robot, optional (profile tu-dong)
[D]PostgreSQL16PostgreSQLMain database, hash-chained audit log
[D]Hasura GraphQL Engine CE2.51.0Apache-2.0Generated GraphQL, row-level permissions by role and unit
[D]PostgREST14.18MITGenerated REST (/rest/v1) for tables of generated apps (sinh schema); units isolated by the harness's RLS
[D]Supabase Studio, postgres-meta2026.10.12, 0.100.0Apache-2.0Platform operators create tables and add columns in sinh (studio profile, only on the server itself)
[D]SeaweedFS4.48Apache-2.0S3-compatible file store, write-locked cold storage for archived records
[D]Meilisearch CE1.54.3MITFull-text search, chunk index of the Q&A assistant
[I]Ollama, Qwen3 weights0.35.1MIT; weights Apache-2.0Local language model, optional (profile ai)
[I]Tesseract OCR5.5.0Apache-2.0Text recognition on scanned and photographed letters
TrustClamAV1.5.4GPL-2.0Malware scanning before storage
TrustOpenBao2.7.1MPL-2.0Secrets vault, encryption keys for restricted documents, internal CA and signing keys
IT/OTScorpio Broker, PostGIS6.0.2, 16-3.5BSD-3-Clause, GPL-2.0NGSI-LD digital twins of sensors (profile iot)
OperationsPrometheus, Alertmanager, Grafana OSS3.15.0, 0.34.1, 13.2.3Apache-2.0, AGPL-3.0Monitoring of the API gateway and each component's status, internal network only; alerts reach the unit admins' notification bell
OperationsVector, Parseable0.59.0, 3.2.4MPL-2.0, AGPL-3.0Centralised logs with personal data masked, optional (profile logs)
OperationsJaeger2.22.0Apache-2.0Distributed tracing across APISIX, svc-files, svc-workflow, optional (profile trace)
Operationsrestic0.19.1BSD-2-ClauseEncrypted backup of databases, files and the vault

Every license is OSI-approved. The GPL and AGPL components (ClamAV, PostGIS, Grafana, Parseable, DokuWiki) run as independent services talking over the network, with no linked code, so they do not conflict with Apache-2.0. The license of every package, transitive ones included, is checked automatically with make license-audit.

Building from source​

System requirements​

ComponentMinimum versionNotes
Docker Engine24.0with the docker compose v2 plugin 2.17+ and docker buildx
GNU Make4.0runs the commands
Python3.10standard library only, nothing to install: sample data, smoke tests, demos, backup, install and operations commands
RAM8 GBthe default profiles (19 services, 18 running continuously) measured about 4.6 GiB on release 1.3.0 (docker stats, 2026-10-31; ClamAV 0.9 GiB, up to 1.9 GiB for about 10 seconds at each signature reload, Meilisearch 0.75 GiB, Keycloak 0.6 GiB, APISIX 0.5 GiB, Hasura 0.4 GiB). Since #569 the default profiles have 21 services, 19 running continuously: rest (PostgREST, about 25 MiB) and the one-shot rest-init; the studio profile adds about 300 MiB (measured in CI on 2026-11-04, #568). The AI profile (ai, both default models loaded) adds about 3.2 GiB, so plan on 16 GB
Free disk10 GBimages about 5 GB; AI models about 2 GB more

Every tool used to build Signet is open-source software. No closed-source or home-made tool is needed.

Steps​

# 1. Get the source
git clone https://github.com/HIT-Champion/Signet.git
cd Signet

# 2. Configure (do NOT edit source code to configure — every parameter lives in .env)
make env # creates .env from .env.example with random passwords; or: cp .env.example .env and edit
make check

# 3. Build the team's images and start everything (first run takes a few minutes: image pulls, ClamAV signatures)
make up

# 4. Load sample data: 2 units, departments, 10 accounts, documents at every step of the workflow
make seed

Open http://localhost:8080 and sign in with an account from Try it out. Stop: make down (keeps data) · wipe all data: make reset · list every command: make help. On a server with a domain name and HTTPS (Caddy in front of APISIX), or on a machine without a public IP such as a laptop or a machine at home (Cloudflare Tunnel, profile tunnel, no port opened): docs/trien-khai.md (Vietnamese).

Installing outside the source tree​

make install builds the team's images tagged with the version, copies docker-compose.yml, .env and the configuration files the containers use to PREFIX, then checks that the installation no longer points back to the source tree. Delete the source tree afterwards and the system keeps running.

sudo install -d -o "$USER" /opt/moc # the install directory belongs to the operator, so make need not run as root
make install PREFIX=/opt/moc
make down # if it is running in the source tree: both share the same data
cd /opt/moc && docker compose up -d --wait
python3 scripts/seed.py # sample data, first time only
  • PREFIX defaults to /opt/moc. The version comes from git describe; when installing from a .tar.gz package, set it by hand: make install PREFIX=/opt/moc MOC_VERSION=0.1.0.
  • If the package has a VERSION file at its root, the version is already recorded there (git archive fills it in when packing) and make install reads it, no need to set it by hand.
  • Upgrade: stop the installation and run make install again with the same PREFIX. Compose, configuration and images are replaced; the installation's .env is kept, except MOC_VERSION, COMPOSE_PROFILES and COMPOSE_FILE, which make install sets again each time. For a running installation with data, use scripts/nang_cap.sh nang /opt/moc: it backs up first, checks afterwards and prints the rollback command (docs/trien-khai.md, section Vận hành).
  • Uninstall: make uninstall PREFIX=/opt/moc removes exactly the installed files, keeping .env and the data.

Try it out​

Online: https://signet.htechcs.com runs the latest release on the team's machine, reaching the Internet through Cloudflare Tunnel; .github/workflows/ban-online.yml checks daily that it runs the newest tag. Trial accounts are sent with the contest submission; the repository does not publish passwords. Since the evening of 31/10/2026 the online site runs v1.4.0 plus fixes merged into develop but not yet tagged: the interface (#470, #481, #495, #500) and the assistant (#496, #503, #504); /api/status still reports 1.4.0. The teaching schedule change app (#483) is added with moc app install. Other unreleased features (the "Chưa phát hành" section of CHANGELOG.md) are available when you install from source. The online assistant writes its answers through an external OpenAI-compatible API (MOC_ASK_API=openai, model gpt-6-luna-wd, not an open-source model): only the question and the supporting passages leave the machine, with ID card numbers, phone numbers, email addresses and bank account numbers masked; names and addresses are not masked. Your own installation uses local Ollama by default (DEPENDENCIES.md).

Your own installation: the shared password of the sample accounts is the value of MOC_DEMO_PASSWORD in .env. Clerks, unit directors, team and division heads, and unit administrators must use two-factor authentication: after the password, enter a TOTP code. make seed gives these accounts a shared key (MOC_DEMO_TOTP_SECRET); make totp prints the current code and the key, which you can add once to an authenticator app on your phone (FreeOTP, Aegis, Google Authenticator). Real accounts in these roles set up TOTP with a QR code on first sign-in.

AccountRoleSees
vanthuClerk, School of ICT (Trường CNTT & TT)Receives and registers; numbers and issues outgoing documents; every document of the unit
truongkhoaHead of the school (Hiệu trưởng)Instruction inbox, signs off outgoing documents; executive dashboard; every document of the unit
totruongdt, truongbmktpmHead of Training, Head of the Software Engineering departmentDocuments assigned to their team or department; assigns work; reviews drafts
chuyenviendt, giamkhao, giangvienktpmOfficer, lecturersDocuments assigned to them; drafts and submits outgoing documents
quantriUnit administratorThe unit's audit log; cannot read document contents
vanthukt, truongkhoaktSchool of Economics (Trường Kinh tế)Only School of Economics documents

Judges can try it quickly as giamkhao (an officer, no TOTP needed): the inbox already holds an urgent letter to handle and a reply draft the team head sent back for changes.

Address on your own installationWhat it isSign-in
http://localhost:8080e-OfficeYes
http://localhost:8080/ca-nhan/P.A.R.A personal spaceYes
http://localhost:8080/tai-lieu-api/API documentation (Swagger UI): the core API and the e-Office API, sign in to try calls through the gatewayOptional
http://localhost:8080/bang-tin/Unit news board, once installed with make app-install APP=apps/bang-tin/app.yamlYes
http://localhost:8080/sinh/Apps generated from tables: lists and forms built from tables created in Studio, once installed with make app-install APP=apps/sinh/app.yamlYes
http://localhost:8080/xac-thucDocument verification portal: enter a code or drop a PDF; codes of the issued sample documents are on each document's detail page (Outgoing documents, Issued tab)No
http://localhost:8080/trang-thaiSystem statusNo
http://127.0.0.1:8180/adminKeycloak admin console, only on the server itself (KEYCLOAK_ADMIN_* account)Yes
http://127.0.0.1:3300Grafana API gateway monitoring, only on the server itself (remotely: SSH tunnel)No
http://127.0.0.1:3400Supabase Studio: platform operators create tables for generated apps, studio profile, only on the server itself (remotely: SSH tunnel)No

Operations and testing​

Administrator tasks on a running installation are described in docs/van-hanh.en.md:

TaskMain command
Adding a unit (faculty, office, member school)python3 scripts/moc.py tenant create …
Backup and restore of every database, file and the vault into an encrypted restic repositorymake backup, make restore
Secrets vault OpenBao: limits, upgrading an old vault for digital signaturesmake demo-ket-bi-mat
GitOps and self-healing: systemd timer or cron, one round a minute; follows the deploy branch or release tags (MOC_GITOPS_FOLLOW=release), upgrades with a backup and rolls back on failure (MOC_GITOPS_MODE=nang-cap); with MOC_GITOPS_ALLOWED_SIGNERS set, applies signed versions onlymake reconcile
Monitoring of the API gateway with Prometheus + GrafanaSSH tunnel to port 3300
Apps generated from tables: create tables in Supabase Studio, PostgREST generates the API, the /sinh page builds formsadd studio to MOC_EXTRA_PROFILES, make up
Centralised logs: Vector + Parseable, searched by request id X-Request-Idmake logs-up, make logs-tra ID=…
IT/OT convergence: NGSI-LD broker, sensorsmake demo-it-ot
Public data: snapshots of Ministry of Education and Training circulars from the Official Gazette, SHA-256 check, data agemake du-lieu-mo
Plugging in an application from a manifest, no core changes; removal keeps datapython3 scripts/moc.py app install …, app list, app remove
Web application firewall: block, log only or off; find a block by X-Request-IdMOC_WAF=On · DetectionOnly · Off
Checking the audit log outside the databasemake audit
CommandWhat it checksNeeds
make testUnit tests of svc-files, svc-workflow and the operations commands; tests of the e-Office, including form validation against schemas/ with the same test cases as the server and database; tests of the personal space, the news board, the leave request app, the teaching schedule change app and the API docs pagePython + uv; Node 24 and npm ci in apps/office
make smokeThe full incoming and outgoing document flows through APISIX; verification portal, WebSocket notifications, audit log; blocking bad data, EICAR, admin paths; unit isolation; rate limits; secrets vault; reconciler; archiving; monitoring; the WAF blocks attack payloads without blocking real dataA running system + make seed
make e2eA real browser (Playwright, in a container): bad forms blocked before sending, dropping a file on the verification page, two users notified at the same time, audit log, dashboard, digital signatureSame as above
make do-doc-van-ban, do-hoi-dap, do-giao-viec, do-che-pii, do-so-lieu-sauMeasure the AI agents on labelled samples (right / wrong / empty per field, recall@3, coverage); the "after" metrics of spec §8A running system (do-che-pii does not need one)
db/tests/Schema, permissions by role and unit, constraints, audit log (including tampering attempts) on real PostgreSQL + Hasurasee db/README.md
make sbom, make license-auditCycloneDX SBOM of the source tree (Syft); the license of every npm package, Python package and CI action, transitive ones included, against the policy in DEPENDENCIES.mdDocker, network access to PyPI

CI runs the table above and the demos on every pull request that changes code: it builds from source with exactly the install commands, rehearses backup and restore, installs into another directory, runs GitOps, and scans for secrets and vulnerable dependencies. Reminders can only be tested with short deadlines: MOC_SLA_DURATION=PT20S make up, then MOC_SLA_DURATION=PT20S make smoke.

Troubleshooting​

SymptomCause and fix
make check reports a missing .env or docker composeRun make env to create .env; install the Docker Compose v2 plugin, 2.17 or newer
make up stops while pulling or building images: a timeout reaching docker.io, or toomanyrequestsThe network blocks Docker Hub, or the anonymous pull limit is used up. Let Docker pull through the mirror.gcr.io mirror (registry-mirrors, needs sudo) as described in section 2b of docs/trien-khai.md (Vietnamese)
make up takes long, services still starting or unhealthyThe first run pulls about 5 GB of images and ClamAV loads its virus signatures, which takes a few minutes; make up waits up to 10 minutes. Watch with make ps, make logs
Port 8080 is already used by another programSet MOC_HTTP_PORT=8081 and MOC_PUBLIC_URL=http://localhost:8081 in .env before the first make up: the Keycloak realm loads this address only once, so if it already ran, make reset and start again
Signing in fails when opened by a LAN IP addressBrowsers only allow Web Crypto (PKCE sign-in, SHA-256 on the verification page) over https or on localhost. Use localhost, or set up HTTPS following docs/trien-khai.md
The TOTP code is rejectedThe phone's clock is off (codes change every 30 seconds): turn on automatic time, or get the code from the server's clock with make totp. After 10 wrong attempts Keycloak temporarily locks the account
"The security gateway blocked this content because some text looks like an attack pattern" (HTTP 403)The WAF in the APISIX gateway saw text that looks like an attack payload. Edit the text or file name and send again. If real data was blocked by mistake, take the request id (X-Request-Id) of the block, find it with docker compose logs apisix | grep <id> and add an exclusion as described in platform/apisix/README.md (Vietnamese); meanwhile you can set MOC_WAF=DetectionOnly (log only) and run docker compose up -d apisix
The machine slows down or runs out of RAM after turning on AIThe model needs up to 6 GB more RAM. Turn it off with docker compose --profile ai stop ollama; the agents fall back to working without a model

Still stuck? Open an issue with the bug report template, including the output of make ps and the make logs excerpt of the failing service.

Documentation​

Most documents are in Vietnamese.

GroupDocuments
Use and operationsDemo script · Operations · Deploying to a server · API documentation · Adding a new application on the core
TechnicalH-P-D-I architecture · Data model and permissions · Product specification · Feature maturity with evidence · AI evaluation · "After" metrics of spec §8 · H-P-D-I self-assessment · Git workflow
ContestPoF self-assessment · Likely jury questions · Theme, rules, judging criteria · Problem statement analysis · Development plan · Research before the problem statement
ProjectCopyright and third-party software · Dependencies and licenses · Change history · Contributing guide · Security policy · Roadmap · Code of conduct

Repository layout​

The team's own code lives in apps/, services/ and db/. platform/ only holds configuration for the open source software the core uses unmodified (official images, no changes to upstream code).

apps/ e-Office (office/, Nuxt 4) · P.A.R.A personal space (ca-nhan/) · unit news board
(bang-tin/), leave requests (nghi-phep/), teaching schedule changes (lich-giang/): three apps
plugged in with moc app install · Swagger UI API documentation (tai-lieu-api/)
services/ svc-workflow/: Hasura Actions, BPMN workflows, notifications, reminders, assignment suggestions
svc-files/: files, quarantine, search, PDF rendering, signing, verification portal, AI agents
ot-sensor/: simulated temperature sensor (profile iot-sim)
db/ PostgreSQL schema, Hasura permissions by role and unit, hash-chained audit log; tests/
schemas/ Form JSON Schemas, shared by the interface, the services and the database
platform/ Configuration for Keycloak, APISIX, Centrifugo, OpenBao, monitoring, centralised logs, systemd
scripts/ Operations commands (moc.py, seed, smoke, backup, audit, reconcile, demo), install, repo tooling
(PR checks, releases, license headers, architecture diagram generator so_do_kien_truc.py)
seed/ tests/e2e/ Fictional sample data · browser tests (Playwright)
docs/ Product documentation; api/: API docs; du-thi/: contest documents
docker-compose.yml The whole system, split into profiles core, app, ai, iot, logs…
Makefile Entry point for every command: make env, up, seed, test, smoke, install…

Signet was formerly named Mộc. The technical codename moc remains in code and configuration: MOC_* variables, realm moc, the scripts/moc.py command, moc/* images, the /opt/moc install directory.

Contributing and contact​

MemberGitHubEmail
Nguyễn Huy HoàngHoangTechCS-AIEnguyenhuyhoangqbx5@gmail.com
Đinh Văn VượngVanvuong2005827vanvuong2005827@gmail.com
Nguyễn Lê Hoài Namnguyenlehoainamnamngyenhoai21@gmail.com

License​

Released under the Apache License 2.0, an OSI-approved license. Full text: LICENSE. Why this license was chosen: NOTICE.

Every file carries copyright and licensing information following the REUSE specification: source files have an Apache-2.0 header (make license-check), and files that cannot hold a header (JSON, images, PDF, docs) are declared in REUSE.toml. Check the whole repository with uvx --from reuse==5.0.2 reuse lint.

Signet orchestrates upstream open-source software in its original form; it does not copy or modify their source code into this repository. The project logos in the architecture diagram are trademarks of their owners, used only to identify the components, and are not covered by Signet's Apache-2.0 license: docs/anh/logo/NGUON.md.