> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vikat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Security at Vikat

> Security practices for Vikat: container hardening, dependency scanning, and reproducible builds.

Vikat is maintained as a local-only repository with no CI/CD pipeline. Security checks are therefore
**run on demand** rather than automatically on every change. The controls below are either enforced in
the source tree, or are commands you should run before shipping an image.

<Warning>
  This repository has no GitHub Actions, Dependabot, CodeQL, or automated SARIF reporting. Nothing scans
  your code unless you invoke it. Every scan on this page must be run manually.
</Warning>

| Domain              | Tool / Practice                                                               | How it runs                         |
| ------------------- | ----------------------------------------------------------------------------- | ----------------------------------- |
| Dependency scanning | Snyk Open Source                                                              | Manual (`snyk test`)                |
| SAST                | Snyk Code                                                                     | Manual (`snyk code test`)           |
| Image scanning      | Docker Scout CLI                                                              | Manual (`docker scout cves`)        |
| Container hardening | Multi-stage build, digest-pinned bases, non-root user, stripped static binary | Enforced in `transports/Dockerfile` |
| Reproducible builds | Pinned Go / Node toolchains, lockfiles, digest-pinned base images             | Enforced in the tree                |

***

## Vulnerability Scanning - Snyk

The repository keeps a Snyk policy file (`.snyk`) that manages vulnerability ignores. Scans are **not**
automated — run them with the [Snyk CLI](https://docs.snyk.io/snyk-cli).

<Tabs>
  <Tab title="Dependency Scanning (Open Source)">
    Scans all Go, Node, and Python dependencies for known vulnerabilities.

    ```bash theme={null}
    snyk test --all-projects --detection-depth=4
    ```

    * Covers every module across `core/`, `framework/`, `transports/`, `plugins/`, `ui/`, and `tests/`
    * Detection depth of 4 catches transitive dependencies
  </Tab>

  <Tab title="SAST (Snyk Code)">
    Static Application Security Testing across the codebase. Build the project first (Go + Node) so Snyk
    can analyze compiled artifacts.

    ```bash theme={null}
    snyk code test
    ```

    * Detects injection flaws, hardcoded secrets, insecure crypto, and other code-level vulnerabilities
  </Tab>
</Tabs>

***

## Container Image Security

### Dockerfile Hardening

`transports/Dockerfile` applies the following, all verifiable in the file itself:

<CardGroup cols={2}>
  <Card title="Multi-stage builds" icon="layer-group">
    Separate UI builder (Node), Go builder, and minimal Alpine runtime stages ensure no build tools or
    source code leak into the final image.
  </Card>

  <Card title="Digest-pinned base images" icon="lock">
    Every `FROM` is pinned to an immutable `@sha256:` digest, not a mutable tag — so a compromised or
    re-pushed tag cannot silently change the build.
  </Card>

  <Card title="Non-root execution" icon="user-shield">
    An unprivileged `appuser` is created with `adduser -D` and the container runs as it via `USER appuser`
    — never as root. The Red Hat image uses numeric `USER 1001`.
  </Card>

  <Card title="Binary stripping" icon="minimize">
    Go binaries are compiled with `-ldflags="-w -s"` to strip debug symbols and DWARF information,
    reducing attack surface and image size.
  </Card>
</CardGroup>

Additional hardening measures:

* **Patched base layers** - `RUN apk upgrade --no-cache` applies the latest Alpine security patches during build
* **Static builds** - Compiled with `-tags "sqlite_static"` and `-extldflags '-static'` for fully static linking
* **Build verification** - `RUN test -f /app/main || exit 1` ensures the binary exists before proceeding
* **Minimal runtime** - The Alpine runtime carries only essential libraries (`musl`, `libgcc`, `ca-certificates`)

```dockerfile theme={null}
# Runtime stage excerpt
FROM alpine:3.23.4@sha256:5b10f432ef3da1b8d4c7eb6c487f2f5a8f096bc91145e68878dd4a5019afde11
WORKDIR /app

COPY --from=builder /app/main .
COPY --from=builder /app/docker-entrypoint.sh .

RUN mkdir -p "$APP_DIR/logs" && \
    adduser -D -s /bin/sh appuser && \
    chown -R appuser:appuser /app
USER appuser

ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["/app/main"]
```

<Note>
  The runtime base is standard Alpine. It is **not** a FIPS 140-2 validated image. If you require FIPS,
  swap the runtime `FROM` for a validated base and re-verify the OpenSSL provider.
</Note>

### Scanning Images Locally

Build the image, then scan it with [Docker Scout](https://docs.docker.com/scout/):

```bash theme={null}
docker build -f transports/Dockerfile -t vikat-gateway:local .
docker scout cves vikat-gateway:local
```

***

## Reproducible Builds

Toolchains and dependencies are pinned in the source tree so builds are deterministic:

| Runtime          | Pinned Version     | Pinned in                                    |
| ---------------- | ------------------ | -------------------------------------------- |
| Go               | `1.26.4`           | `go` directive in each `go.mod`; `flake.nix` |
| Node             | `22.12.0`          | `.nvmrc`                                     |
| Python test deps | Locked             | `tests/integrations/python/uv.lock`          |
| Container bases  | `@sha256:` digests | `transports/Dockerfile`                      |

Go module checksums are enforced through each module's `go.sum`, and the UI dependency tree is locked in
`ui/package-lock.json`.

***

## Controls removed with CI

The upstream project relied on GitHub-native automation that does **not** exist in this repository. If you
need equivalent coverage, you must reintroduce it yourself:

| Removed control              | What it did upstream                                   | Local substitute                           |
| ---------------------------- | ------------------------------------------------------ | ------------------------------------------ |
| Dependabot                   | Weekly dependency-update PRs across gomod, npm, Docker | `go get -u`, `npm outdated`, manual review |
| CodeQL                       | Semantic analysis on every push/PR                     | `snyk code test`                           |
| Snyk CI jobs                 | Scanned on every push/PR, uploaded SARIF               | Run the Snyk CLI manually (above)          |
| Actions SHA pinning          | Pinned all workflow actions to commit SHAs             | N/A — no workflows                         |
| npm provenance               | SLSA attestations on published packages                | N/A — nothing is published                 |
| StepSecurity / harden-runner | Hardened CI runners, egress allowlists                 | N/A — no runners                           |
| CODEOWNERS                   | Review gates on security-critical paths                | N/A — no pull requests                     |
