Cross-service shared definitions that eliminate manual synchronization between MonadIAM services.
Local Code Graph (Graphify)
Install once with uv, then open a new terminal:
uv tool install graphifyy==0.9.65
uv tool update-shellRun make graphify from the repository root to create or update the local code
graph and report. No API key is required. Outputs in graphify-out/ are ignored
by Git. Agent guidance: AGENTS.md.
Local TypeScript Navigation (LSP-MCP)
lsmcp and TypeScript Language Server are pinned
dev dependencies. Install with pnpm install using the Node version from
package.json. Run make lsp from the repository root to start the stdio MCP
server; an MCP client must connect to it to issue queries.
For an MCP client, use command node, arguments
["node_modules/@mizchi/lsmcp/dist/lsmcp.js", "--config", ".lsmcp/config.json"],
and set its working directory to this repository. Desktop clients may need an
absolute Node executable path. Configuration: .lsmcp/config.json.
Local indexes and caches are ignored by Git. Agent guidance: AGENTS.md.
TypeScript navigation covers local declarations in src. Protobuf and Kafka
JSON schemas are checked separately with make check.
Contracts
The package keeps TypeScript contracts and the schema artifacts registered in the Schema Registry:
- TypeScript service contracts are written manually in
src/types.ts. - gRPC protobuf files in
src/grpcare used by NestJS gRPC transport. - Kafka JSON Schemas in
src/kafkaare registered fromcatalog.json. - The build does not generate TypeScript types from
.protofiles.
Consumers should resolve gRPC protobuf files through package subpaths instead of importing path constants:
const protoPath = require.resolve("@monadiam/shared/grpc/access_control.proto");Registry publication is performed by the scripts in this repository, not during service startup.
Database seed datasets
Seed datasets are compiled and shipped with this package, grouped by service:
import { dataset, bootstrap } from "@monadiam/shared/datasets/access-control";
dataset.Roles.redis;
bootstrap.ADMIN_PERMISSION_CODES;Individual modules keep their original names and named exports, for example
@monadiam/shared/datasets/identity/interface-client.dataset.
Database connections, migrations, seed execution order, and Redis Lua scripts remain in the consuming services. Import datasets through their subpaths; the package root exports only common definitions and does not load seed data.
Schema Registry
Source: catalog.json; artifact paths are relative to src/.
| Protocol | Format | API | Group | Artifact |
|---|---|---|---|---|
| Kafka | JSON | /apis/ccompat/v7 |
default |
<topic>-value |
| gRPC | Protobuf | /apis/registry/v3 |
monadiam.grpc |
<service> |
Kafka clients load schemas from Apicurio. gRPC loads .proto from @monadiam/shared;
registry publication stores the contract. Catalog groupId applies only to gRPC.
| Script / image | Responsibility |
|---|---|
| check.sh | Check catalog, files, JSON syntax and proto3 headers |
| verify.sh | Check compatibility; create no groups or artifacts |
| apply.sh | Publish schemas; identical content reuses its version |
| registry.sh | Configuration, HTTP timeouts and error details |
| Dockerfile | Catalog + scripts; Bash/curl/jq; UID/GID 65532 |
# Local: configure .env first (see Environment).
make check
make verify
make apply
# Image: default command is scripts/apply.sh.
make image IMAGE=monadiam/shared-schemas:localIn containers, provide SCHEMA_REGISTRY_URL; select scripts/verify.sh or
scripts/apply.sh. Read-only filesystem is supported. Planned stand order:
Apicurio Ready -> Job (verify -> apply) -> services.
| Execution rule | Behavior |
|---|---|
| New gRPC group | Local check only; full server validity check on publication |
| Partial failure | Previous writes remain; rerun after correcting the error |
| HTTP failure | Nonzero exit, status and response body; no automatic retries |
Container package (GHCR)
Image: ghcr.io/monadiam/shared-schemas (linux/amd64).
Workflows: CI, publish, release.
Publication and retention: packages.sh.
| Event / setting | Behavior |
|---|---|
| PR / merge queue | Checks and image build; no publication |
| Merge into main | Build and publish image as sha-<full commit SHA> |
Git tag vX.Y.Z |
Require package.json.version = X.Y.Z; add image tag X.Y.Z |
| Release image | Reuse published SHA digest; no rebuild or tag overwrite |
| Stand | Pin release as <image>:<version>@sha256:<digest> |
| Retention | Keep last 10 SHA builds and current commit |
| Protected images | Keep releases, custom tags and untagged manifests |
| Authentication | CI uses GITHUB_TOKEN; public pulls require no credentials |
Environment
Create local variables from the example file:
make env| Variable | Example | Purpose |
|---|---|---|
SCHEMA_REGISTRY_URL |
http://localhost:8081 |
Apicurio Registry base URL |
SCHEMA_REGISTRY_API_PATH |
/apis/registry/v3 |
Apicurio native API path |
SCHEMA_REGISTRY_CCOMPAT_PATH |
/apis/ccompat/v7 |
Confluent compatibility API path |
SCHEMA_REGISTRY_CONNECT_TIMEOUT_SECONDS |
5 |
Maximum connection time, seconds |
SCHEMA_REGISTRY_REQUEST_TIMEOUT_SECONDS |
30 |
Maximum complete request time, seconds |
All five settings are required. Local scripts read .env; the image declares API
paths and timeouts through ENV, and requires SCHEMA_REGISTRY_URL at runtime.
Missing or empty values fail immediately; scripts do not supply fallback values.
Commands
| Makefile | Description |
|---|---|
| Development | |
make build |
Compile the package into dist. |
make lint |
Run ESLint. |
make lint-fix |
Fix only Prettier violations and print changed file paths. |
make tsc |
Check TypeScript with tsc --noEmit. |
make knip |
Run Knip. |
make secrets-check |
Run the hook secret scan (staged changes). |
make lsp |
Start the local TypeScript MCP server over stdio. |
make graphify |
Create or update the local code graph and Markdown report. |
make graphify-rebuild |
Rescan all code files and regenerate the report. |
make graphify-html |
Update the graph and report, then export HTML visualization. |
| Schema Registry | |
make env |
Create .env from .env.example. |
make check |
Check catalog, artifact files, JSON syntax and proto3 headers; no network. |
make verify |
Check schema compatibility; create no groups or artifacts. |
make apply |
Publish schemas to Apicurio; identical content reuses its version. |
| Container / GHCR | |
make image |
Build catalog/scripts image; configurable IMAGE and VCS_REF. |
make image-publish |
Publish existing monadiam/shared-schemas:ci as sha-<HEAD> in GHCR. |
make image-release |
Assign the package version to the published SHA image; no rebuild. |
make image-cleanup |
Delete old SHA images according to the GHCR retention policy. |
GHCR targets run in Actions with GITHUB_TOKEN; publish/release also require
GITHUB_STEP_SUMMARY, and release requires GITHUB_REF_NAME.
Installation
The package is distributed directly from git and is not published to npm. To install in a consuming project:
pnpm add git+https://github.com/MonadIAM/shared.git#v2.0.0A version tag after
#is required. Without it, pnpm will resolve to the latest commit on the default branch.
Releasing a new version
-
Create a branch from current
main:git switch main git pull --ff-only origin main git switch -c feat/message-templates
-
Make changes and update
package.json.versionto the next release version. Schema and TypeScript changes share this version. -
Commit and push the branch:
git add . git commit -m "feat: add new message templates" git push -u origin feat/message-templates
-
Open a PR into
main. Wait for required checks, including CI passed, then merge. Wait for Publish schema image to succeed for the resulting commit: it builds and publishesghcr.io/monadiam/shared-schemas:sha-<commit SHA>. -
Update local
main. Its latest commit should be your published release commit:git switch main git pull --ff-only origin main
-
Create and push the tag matching
package.json.version(example:2.0.20):git tag v2.0.20 git push origin v2.0.20
-
Wait for Release schema image. It verifies
vX.Y.Zagainstpackage.json.versionand adds image tagX.Y.Zto the published SHA image without rebuilding. Use the digest from the workflow summary in stand.