npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@educreds/connector-agent

v1.0.0

Published

EduCreds Connector Agent — on-premises SIS/LMS integration bridge for automated credential issuance

Readme

EduCreds Connector Agent

Package: @educreds/connector-agent Version: 1.0.0 Deployed by: the institution, on-premises (or in an institution-controlled VPC) Contract with EduCreds cloud: HTTPS + HMAC + optional mTLS

This is the institution-side half of the Tier 1 (Enterprise Connector) and Tier 2 (Cloud Connector) architecture. It is a small, hardened Fastify server that exposes a fixed contract of read/write endpoints against your SIS. It is the only piece of EduCreds software that lives inside your data centre; nothing else needs to be installed on your side.

Corresponding cloud-side client: cert_backend/src/providers/connector/ (ConnectorHttpClient + EnterpriseConnectorProvider + CloudConnectorProvider).


What it does

  • Accepts HMAC-signed HTTPS requests from the EduCreds cloud.
  • Optionally enforces mutual TLS (recommended for Tier 1).
  • Fetches student, graduation, programme and transcript records from your SIS.
  • Writes back status updates (e.g. "credential minted" / "revoked").
  • Emits an append-only JSONL audit log for regulatory review.

What it does NOT do

  • Never persists EduCreds cloud data locally. All state is your SIS.
  • Never transmits raw PII in-clear. Requests are HMAC-signed; mTLS is the transport wrapper. If you use Tier 1, encryption of specific fields at rest before transmission is handled by your SIS export layer, not by this agent.
  • Never trusts request bodies without HMAC verification. Anonymous requests are rejected with 401.

Directory layout

connector-agent/
├── src/
│   ├── adapters/            # SIS adapters (Postgres/MySQL/MSSQL/Oracle/SQLite)
│   ├── middleware/          # HMAC guard
│   ├── routes/              # Fastify route bindings
│   ├── utils/               # config loader, audit logger
│   └── index.ts             # entrypoint
├── config/
│   └── connector-config.example.yaml
├── Dockerfile               # multi-stage, non-root, distroless-shaped
├── docker-compose.yml       # reference deployment
├── package.json
├── tsconfig.json
└── README.md                # (this file)

Quickstart (Docker)

cd connector-agent
cp config/connector-config.example.yaml connector-config.yaml
$EDITOR connector-config.yaml           # fill SIS SQL, institution id
cat > .env <<'EOF'
EDUCREDS_CONNECTOR_SHARED_SECRET=<32+ char shared secret from EduCreds onboarding>
EDUCREDS_INSTITUTION_ID=<uuid from EduCreds onboarding>
SIS_DB_HOST=your.sis.internal
SIS_DB_NAME=sis_production
SIS_DB_USER=educreds_reader
SIS_DB_PASSWORD=…
EOF
mkdir -p certs && cp /path/to/institution.crt /path/to/institution.key /path/to/educreds-ca.crt certs/
docker compose up -d

Verify:

curl -k https://localhost:8443/healthz
# {"status":"ok","adapter":"postgres","at":"2026-01-…"}

Quickstart (local dev without Docker)

yarn install
export CONNECTOR_CONFIG_PATH=$PWD/connector-config.yaml
yarn dev

HTTP contract

Every non-/healthz//readyz//health//agent-info request MUST carry:

| Header | Value | |---------------------------|-----------------------------------------------------------------------| | X-EduCreds-Timestamp | Unix milliseconds. Rejected if >5 min from server clock. | | X-EduCreds-Signature | HMAC_SHA256(sharedSecret, canonical) in hex. | | X-Institution-Id | Institution id. When configured, must equal the agent's institutionId. |

This scheme is byte-for-byte identical to the cloud client (cert_backend/src/providers/connector/connector-http.client.ts::sign) and to the inbound guard (connector-signature.guard.ts). There is no nonce — the cloud signs each request uniquely; do not add one or the two sides will fail to authenticate each other.

Canonical string:

<TIMESTAMP>\n
<METHOD>\n
<PATH_WITHOUT_QUERY>\n
sha256(<RAW_BODY>)      # empty string when there is no body

Endpoints

| Method | Path | Purpose | |--------|---------------------------------------------|----------------------------------------| | GET | /students/:studentId | Resolve a student by id | | GET | /students/:studentId/transcript | Full course-level transcript | | GET | /graduations/:graduationId | Fetch a single graduation record | | GET | /programmes/:programmeId | Fetch a programme / degree | | GET | /institution | Institution identity + signing key | | POST | /status-updates | Status write-back (body: {entityType, entityId, status, reason?}) | | POST | /credentials | Record a minted credential (body: ConnectorCredentialPayload) | | GET | /healthz | Liveness (no auth) | | GET | /health | Readiness probe used by cloud healthCheck (no auth) | | GET | /readyz | Readiness incl. adapter ping (no auth) | | GET | /agent-info | Read-only metadata for the cloud ConnectorManager (no auth) |

Responses match the schemas in cert_backend/src/providers/connector/connector-response.schema.ts. Deviations are rejected by the cloud with ConnectorValidationError.

GET /agent-info (no auth) returns a small JSON object used by the cloud ConnectorManager to enrich Tier 1 descriptors:

{
  "status": "ok",
  "institutionId": "inst-123",
  "adapterKind": "sqlite",
  "agentVersion": "2.0.0",
  "mtls": false,
  "cloudPushEnabled": false,
  "rateLimit": 1000,
  "reportedAt": "2026-07-16T00:00:00.000Z"
}

If the configured institutionId does not match the agent's own id, the agent returns 409 institution_id_mismatch (defensive; the cloud treats any missing or mismatched response as agentInfo: null). The version field is read from the agent config (version: ${AGENT_VERSION}) and defaults to unknown when unset.

Adding a new SIS adapter

  1. Create src/adapters/<vendor>.adapter.ts implementing IConnectorAdapter.
  2. Wire the adapter kind in src/index.ts bootstrap switch.
  3. Extend config.ts AgentConfig.adapter union.
  4. Add an example config to config/connector-config.example.yaml.

Currently shipped (all on-prem, same contract):

| Dialect | Adapter | Placeholder style | Default port | |---------|---------|------------------|--------------| | PostgreSQL | PostgresAdapter | $1, $2, … | 5432 | | MySQL / MariaDB | MysqlAdapter | ? | 3306 | | SQL Server / Azure SQL | MssqlAdapter | ? (rewritten to @pN) | 1433 | | Oracle | OracleAdapter | ? (rewritten to :1, :2 …) | 1521 | | SQLite | SqliteAdapter | ? (Node ≥22.5 node:sqlite) | file |

oracledb is an optional dependency (native build) — install it only on Oracle institutions. SqliteAdapter uses Node's built-in node:sqlite, so the published image runs Node 22; on-prem npm installs that only use Postgres/MySQL/MSSQL/Oracle can stay on Node 20, but SQLite requires ≥22.5. A new dialect only needs a src/adapters/<vendor>.adapter.ts implementing IConnectorAdapter — routes and middleware are untouched.


Security posture

  • Runs as unprivileged educreds user inside a read-only container.
  • All Linux capabilities dropped (cap_drop: ALL).
  • HMAC secret rotation: coordinate with the EduCreds admin /api/institutions/admin/:id/connector/rotate-secret endpoint. The connector agent MUST be updated with the new secret within 15 minutes of rotation.
  • mTLS: strongly recommended for Tier 1 (production). See docker-compose.yml volume mount for /etc/educreds/certs.
  • Rate limiting: 300 req/min per client IP or per mTLS subject CN. Adjust in config.
  • Audit log: append-only JSONL, one file per day, mode: 0o640. Never rotated by the agent — configure logrotate on the host.
  • Egress depends on the deployment mode:
    • Pull-only (no cloud: block): the cloud polls the agent, so the agent needs no egress beyond the SIS network.
    • Event-driven / push (recommended, default cloud.callbackBaseUrl set): the agent does egress to https://api.educreds.xyz:443 to push graduation.detected and status updates. Allow that hostname in the egress policy.
  • Prerequisites that bite people: accurate host clock (NTP) — the HMAC replay window is ±5 min; a drifting clock 401s every request. The agent's mTLS server must trust educreds-ca.crt or the cloud's client-cert handshake fails.

Health / observability

  • GET /healthz — liveness (no auth). Returns { status: "ok" } even if the adapter is offline.
  • GET /readyz — readiness (no auth). Fails 503 if the SIS ping fails.
  • GET /agent-info — read-only metadata (no auth). Surfaced by the cloud ConnectorManager to enrich Tier 1 descriptors with adapter kind, agent version, and capability flags.
  • Structured JSON logs on stdout via pino. Signature headers are redacted.
  • The audit log directory (/var/log/educreds/audit) is the primary regulatory record; ship it to your SIEM.

FAQ

Q: Why not run this as a Lambda / serverless? A: On-prem SIS databases usually live behind institution firewalls with no public egress. A long-lived host inside the same network segment is the cheapest and safest topology.

Q: What if my SIS is not any of the shipped adapters? A: Implement IConnectorAdapter (~150 LOC) against your driver of choice. Or expose a thin REST layer in front of your SIS and adapt against that.

Q: How do I test integration end-to-end? A: Use the EduCreds staging cloud (https://api-staging.educreds.xyz), point your connector agent at a staging SIS replica, and run the documentation/operations/CONNECTOR_INTEGRATION_TEST.md scenario (see the repo docs). The agent's /healthz and /readyz must both be green for the cloud to enable issuance to your institution.


Distribution & install methods (Tier 1 self-install)

The agent is shipped as a single hardened Docker image. Institutions never need a Node toolchain. Three supported install paths:

1. One-line installer (recommended for IT teams)

curl -sSL https://get.educreds.xyz/connector | bash

The script installs Docker if missing, creates /opt/educreds-connector and /etc/educreds, writes docker-compose.yml + .env from your onboarding pack, and verifies /healthz. Non-interactive / config-management usage:

EDUCREDS_INSTITUTION_ID=... EDUCREDS_CONNECTOR_SHARED_SECRET=... \
SIS_DB_HOST=... SIS_DB_NAME=... SIS_DB_USER=... SIS_DB_PASSWORD=... \
curl -sSL https://get.educreds.xyz/connector | bash -s -- --systemd

After install, edit /etc/educreds/connector-config.yaml to match your SIS schema and drop your mTLS certs into /opt/educreds-connector/certs/.

2. npm CLI (@educreds/connector-agent)

npx @educreds/connector-agent init

Scaffolds connector-config.yaml, .env, docker-compose.yml, and a systemd unit from your onboarding answers (or from EDUCREDS_* env vars when run non-interactively). It only writes files — starting the service is left to Docker/systemd. Health probe: npx @educreds/connector-agent healthcheck.

3. Pull the image directly

Image: ghcr.io/educreds/connector-agent:1.0.0. Build/push is automated by .github/workflows/connector-cd.yml (tags v*:x.y.z + :latest; manual dispatch → :edge). Institutions just run the bundled docker-compose.yml against the published image.

All three methods produce the same on-prem topology: a read-only, cap_drop: ALL, mTLS container listening on 8443, with the audit log volume-mounted to the host for SIEM shipping.