@misar/guards (0.1.0)

Published 2026-07-21 05:36:03 +00:00 by misaradmin

Installation

@misar:registry=
npm install @misar/guards@0.1.0
"@misar/guards": "0.1.0"

About this package

@misar/guards

Zero-dependency CI guard CLI for the Misar AI monorepo. One package consolidates the scattered check-*.mjs guard scripts so a fix lands once and every repo consumes it. Pure Node.js ESM — Node built-ins only, no install step required to run.

Install / run

It is published to the private Forgejo registry (@misar scope). In a repo that already has the @misar scope wired in .npmrc:

pnpm add -D @misar/guards
pnpm misar-guards           # blocking mode (exit 1 on findings)

Or run without adding a dep (the bin resolves from the workspace or the registry):

npx @misar/guards --advisory      # warn-only ramp
node packages/guards/bin/misar-guards.mjs --help   # from the misar-io monorepo

The CLI reads guards.config.json from the current working directory (the repo root), so run it from the repo root in CI.

CLI contract

misar-guards [options]

--advisory        Emit ::warning annotations and ALWAYS exit 0 (ramp mode).
--only=<ids>      Run only these guard ids (comma-separated). Bypasses the
                  config enable/disable — listed guards run with their options.
--json            Machine-readable JSON: { ran, counts, advisory, findings }.
--config=<path>   Use a config file at <path> instead of ./guards.config.json.
--list            List all guard ids + whether each is default-on. Exit 0.
-h, --help        Show help.

Exit codes: 0 no findings (or --advisory) · 1 findings in blocking mode · 2 usage/config error.

Output is Forgejo-Actions annotations, one per finding:

::error file=src/foo.ts,line=42,title=misar-guards/brand-colors::Banned Tailwind color family "purple-*" …

with a one-line summary of counts at the end.

Config (guards.config.json)

{
  "$schema": "…/guards.schema.json",   // optional
  "advisory": false,                    // optional; same as --advisory
  "ignore": ["packages/guards"],        // optional; repo-relative path prefixes to skip
  "guards": {
    "<guard-id>": true | false | { ...options }
  }
}

ignore entries are repo-relative path prefixes (also matched as substrings), applied to every guard's file scan. In the misar-io monorepo, add "packages/guards" to ignore — the guards package necessarily names the very patterns it detects (VPS IPs, banned URLs, banned SDK names), so scanning its own source would self-flag. node_modules, .next, dist, build, .turbo, out, coverage are always skipped.

Resolution:

  • A guard listed in guards:
    • true → enabled, no options.
    • { ...options } → enabled with those options (add "enabled": false to disable an options block).
    • false → disabled, even if it is in the default set.
  • A guard not listed → enabled iff it is in the default set (below). Opt-in guards must be listed to run.

Copy guards.config.example.json to guards.config.json and trim to taste.

Guards

Default-on (universal — run unless disabled)

id checks
banned-ai-sdk-imports Imports of @anthropic-ai/sdk, @google/generative-ai, @mistralai/mistralai (and friends), and openai used with OpenAI directly (OPENAI_API_KEY / api.openai.com) instead of the assisters gateway.
banned-env-vars ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY / GEMINI_API_KEY in source and .env*; ASSISTERS_API_KEY in internal code (should be ASSISTERS_DEV_INTERNAL_KEY); the wrong gateway path …/api/v1 (should be …/v1).
platform-boundary-imports Cross-platform package imports. Option banScope (default @assisters) — set to @misar in the assisters repo.
brand-colors Tailwind purple-*/violet-*/fuchsia-*/indigo-* utilities and the 9 banned hexes.
api-url-centralization www.misar.io/api/*, misar.io/api/*, and product-domain API paths (mail.misar.io/api, misar.dev/api, …). Requires api.misar.io/<slug>/*.
file-locations .md only in docs/** + root README/CLAUDE/MISAR; test files (*.test.*/*.spec.*) only under tests/**; no packages/ dir and no content/docs/** MDX unless isMisarIo: true.
npmrc-policy .npmrc scopes @misar/@assisters to Forgejo, no global registry= line, token var NPM_TOKEN (not FORGEJO_NPM_TOKEN).
hardcoded-secrets Hardcoded VPS IPs (167.114.185.18, 77.42.113.248) and high-confidence secret shapes (sk-…, sk_live_…, GitHub/Slack tokens, PEM keys).
status-url Status/uptime links to any host other than status.misar.io.
legal-identity-placeholders "Pending registration" / "Coming soon" / "Not yet registered" in legal/footer copy (canonical company identity required).
og-and-matcher Ported from check-og-coverage.mjs: root OG card presence, middleware config.matcher must exempt OG routes and webhook/unsubscribe routes, catches the .*og auth-bypass footgun, plus a favicon/icon-set presence check.

Opt-in (off unless listed — repo-specific)

id checks options
reach-db-routing Reach-only tables (reach_*, global_leads, autopilot_runs, linkedin_*, direct_mail_*, social_channel_configs, lead_search_history, privacy_requests) accessed via the mail client (createAdminClient() / NEXT_PUBLIC_SUPABASE_URL) with no reachOwnedAdmin().
migration-targets Every supabase/migrations/*.sql declares -- misar:target=reach|mail|both. dir, headerLines
sitemap-robots-drift App sitemap.ts stays empty; answerBots/trainingBots arrays stay in lockstep between app and landing robots. appSitemap, appRobots, landingRobots

Run misar-guards --list for the live list.

The --advisory ramp

Introducing guards into a repo with pre-existing violations shouldn't wedge the build. Ramp in three steps:

  1. Observe — run misar-guards --advisory in CI. Every finding is a ::warning and the job stays green. Read the annotations, size the backlog.
  2. Fix — clear the findings guard-by-guard. Use --only=<id> locally to focus (misar-guards --only=brand-colors).
  3. Enforce — drop --advisory (or set "advisory": false). Findings now fail the build (exit 1). Optionally keep a newly-added noisy guard advisory in config while the rest block.

Commit-message hook

misar-commit-msg is a zero-dep validator for .husky/commit-msg. It rejects a Co-Authored-By trailer, any "Claude"/"AI"/"Anthropic" mention (whole-word, case-insensitive), and a subject that isn't conventional-commit type(scope): desc (feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert). Merge/revert/fixup subjects pass through.

# in a repo with @misar/guards installed
npx husky init                                       # or: mkdir -p .husky
printf '%s\n' 'npx --no -- misar-commit-msg "$1"' > .husky/commit-msg
chmod +x .husky/commit-msg

Git passes the commit-message file path as $1; a violation exits non-zero and blocks the commit with a helpful message.

Programmatic use

import { GUARDS, GUARDS_BY_ID, DEFAULT_GUARDS } from "@misar/guards";
import { validateCommitMessage } from "@misar/guards/commit-msg";

const { ok, errors } = validateCommitMessage("feat(x): do a thing");

Each guard exports { id, title, run(ctx) -> findings[] }; a finding is { guard, file, line, message, severity } (severity is "error" or "warning").

Keywords

misar ci guards lint brand og
Details
npm
2026-07-21 05:36:03 +00:00
3
21 KiB
Assets (1)
Versions (2) View all
0.2.0 2026-08-06
0.1.0 2026-07-21