Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:

- name: Restore
if: ${{ needs.changes.outputs.dotnet == 'true' }}
run: dotnet restore Vyral.sln
run: dotnet restore Vyral.sln --locked-mode

- name: Verify Azure Durable package coherence
if: ${{ needs.changes.outputs.dotnet == 'true' }}
Expand Down Expand Up @@ -126,6 +126,8 @@ jobs:
cache-dependency-path: |
clients/python/pyproject.toml
runtimes/python/pyproject.toml
runtimes/python/requirements-server.in
runtimes/python/requirements-server.lock

- name: Set up Go
if: ${{ needs.changes.outputs.go == 'true' }}
Expand Down Expand Up @@ -184,6 +186,7 @@ jobs:
python3 scripts/verify-markdown-links.py
python3 scripts/verify-publication-cohort.py
python3 scripts/verify-publication-policy.py
python3 scripts/verify-python-server-lock.py
python3 scripts/generate-sdk-types.py
python3 scripts/sync-python-runtime-contracts.py
git diff --exit-code
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ permissions:
jobs:
scope:
name: Select CodeQL languages
if: ${{ github.event_name == 'workflow_dispatch' || vars.VYRAL_ENABLE_AUTOMATED_WORKFLOWS == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 5
outputs:
Expand All @@ -44,9 +43,6 @@ jobs:
analyze:
name: Analyze ${{ matrix.language }}
needs: scope
# The repository variable is the emergency pause switch for hosted gates.
# Manual dispatch remains available for controlled diagnostics.
if: ${{ github.event_name == 'workflow_dispatch' || vars.VYRAL_ENABLE_AUTOMATED_WORKFLOWS == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/container-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ permissions:
jobs:
scan:
name: Scan current container surfaces
# Manual dispatch remains available when the hosted-automation pause switch is active.
if: ${{ github.event_name == 'workflow_dispatch' || vars.VYRAL_ENABLE_AUTOMATED_WORKFLOWS == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ permissions:
jobs:
review:
name: Review dependency changes
# The repository variable is the emergency pause switch for hosted gates.
# Manual dispatch remains available for controlled diagnostics.
if: ${{ github.event_name == 'workflow_dispatch' || vars.VYRAL_ENABLE_AUTOMATED_WORKFLOWS == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/execution-runtime-consumer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,6 @@ on:
jobs:
validate:
name: Validate consumer path
# The repository variable is the emergency pause switch for hosted gates.
# Manual dispatch remains available for controlled diagnostics.
if: ${{ github.event_name == 'workflow_dispatch' || vars.VYRAL_ENABLE_AUTOMATED_WORKFLOWS == 'true' }}
runs-on: ubuntu-latest
env:
DOTNET_CLI_TELEMETRY_OPTOUT: "1"
Expand All @@ -92,7 +89,7 @@ jobs:
cache: false

- name: Restore
run: dotnet restore Vyral.sln
run: dotnet restore Vyral.sln --locked-mode

- name: Validate local consumer contract
run: scripts/validate-execution-runtime-consumer.sh
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-first-cohort.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
set -euo pipefail
python -m pip install --disable-pip-version-check build==1.3.0
python3 scripts/verify-publication-cohort.py
dotnet restore Vyral.sln
dotnet restore Vyral.sln --locked-mode
mkdir -p artifacts/publish/nuget artifacts/publish/npm artifacts/publish/pypi
for project in \
src/Vyral.Abstractions/Vyral.Abstractions.csproj \
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/release-integrity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ permissions:
jobs:
verify:
name: Verify releasable artifacts
# The repository variable is the emergency pause switch for hosted gates.
# Manual dispatch remains available for controlled diagnostics.
if: ${{ github.event_name == 'workflow_dispatch' || vars.VYRAL_ENABLE_AUTOMATED_WORKFLOWS == 'true' }}
# Ubuntu 24.04 restricts unprivileged user namespaces through AppArmor. The workspace-agent
# security gate must exercise Bubblewrap's real namespace boundary, never an unsandboxed
# fallback, so keep this job on the supported 22.04 runner until a reviewed AppArmor profile
Expand Down
4 changes: 4 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
<PackageTags Condition="'$(PackageTags)' == ''">vyral;provider-neutral;contracts;retrieval;execution</PackageTags>
<PackageReadmeFile Condition="'$(PackageReadmeFile)' == '' and '$(IsPackable)' != 'false'">README.md</PackageReadmeFile>
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
<!-- Lock the resolved NuGet graph. CI must never silently refresh a transitive
dependency; dependency updates deliberately regenerate the committed locks. -->
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<RestoreLockedMode Condition="'$(CI)' == 'true'">true</RestoreLockedMode>
</PropertyGroup>

<!-- Packages without a package-specific README receive a compact package landing page rather
Expand Down
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ FROM mcr.microsoft.com/dotnet/sdk:10.0@sha256:e1fc6e423f543119c406d24e2e687d67c5

WORKDIR /src
COPY . .
RUN dotnet publish src/Vyral.Server/Vyral.Server.csproj \
RUN dotnet restore src/Vyral.Server/Vyral.Server.csproj --locked-mode --disable-parallel \
&& dotnet publish src/Vyral.Server/Vyral.Server.csproj \
-c Release \
-o /app/publish \
--no-restore \
/p:UseAppHost=false \
&& mkdir -p /app/publish/.vyral

Expand All @@ -21,6 +23,7 @@ LABEL org.opencontainers.image.title="Vyral Server" \

WORKDIR /app
ENV ASPNETCORE_URLS=http://0.0.0.0:8080 \
Server__RequireApiKey=true \
CanonicalStore__Enabled=false \
DatabasePath=/app/.vyral/vyral.sqlite \
ObjectsPath=/app/.vyral/objects \
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,20 +156,26 @@ filesystem. This local command keeps state in a Docker-managed volume:
```bash
docker build -t vyral-server .
docker volume create vyral-data
export VYRAL_API_KEY="$(openssl rand -hex 32)"
docker run --rm \
--publish 127.0.0.1:8080:8080 \
--read-only \
--mount type=volume,source=vyral-data,target=/app/.vyral \
--cap-drop ALL \
--security-opt no-new-privileges=true \
--pids-limit 256 \
--env VYRAL_API_KEY \
vyral-server
```

CanonicalStore routes are disabled in the image unless their identity policies
are explicitly configured. Shared deployments should also use an authenticated
ingress and a deployment-managed API key. See
[CanonicalStore guide](docs/concepts/canonical-store.md) and the [deployment guide](deploy).
are explicitly configured. The image requires an API key before it starts;
health and readiness remain public while data-plane routes require
`X-Vyral-Api-Key` or `Authorization: Bearer …`. This key establishes one
application trust boundary, not multi-tenant authorization. Shared deployments
also need TLS, rate limits, authenticated ingress, and deployment-specific
identity policy. See the [CanonicalStore guide](docs/concepts/canonical-store.md)
and the [deployment guide](deploy).

## Choose a runtime or client

Expand Down
23 changes: 19 additions & 4 deletions runtimes/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,25 @@ work to admit a new run. Use `--path` or `--root` when you need non-default code
or state locations.

Use `--json` with `init`, `quickstart`, or `inspect` for machine-readable
output. `vyral-runtime` remains a compatibility command alias. No wheel has
yet been published, so direct source use or the editable install is the public
pre-release path. Once the authorized wheel is available, install it with
`python -m pip install vyral` without changing the local commands.
output. `vyral-runtime` remains a compatibility command alias. Install the
published runtime with `python -m pip install vyral` without changing the
local commands.

### Reproducible server deployment profile

The published REST/MCP host has a separate hash-verified profile for the
current release. From a source checkout, create an isolated environment and
install the pinned runtime and server dependencies together:

```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --require-hashes -r runtimes/python/requirements-server.lock
```

This profile is intentionally release-specific. Regenerate it when changing
the published Python version or its `server` extra; development extras and
experimental integrations remain separate, opt-in dependency choices.

From a source checkout, run the generated application through the same launcher
that created it so no editable installation is required:
Expand Down
3 changes: 3 additions & 0 deletions runtimes/python/requirements-server.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# The published Python host and its production server extra. Keep this version
# aligned with pyproject.toml; regenerate requirements-server.lock on release.
vyral[server]==0.1.1
24 changes: 24 additions & 0 deletions runtimes/python/requirements-server.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This file is autogenerated by pip-compile with Python 3.12 using:
#
# pip-compile --generate-hashes --strip-extras \
# --output-file=runtimes/python/requirements-server.lock \
# runtimes/python/requirements-server.in
#
# It is the reproducible, hash-verified deployment profile for the published
# Python REST/MCP host. Update its input and regenerate it for a new release.
click==8.4.2 \
--hash=sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6 \
--hash=sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76
# via uvicorn
h11==0.16.0 \
--hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \
--hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
# via uvicorn
uvicorn==0.52.3 \
--hash=sha256:116af2710dbf47c80f463cd20ee4884b6662f4c9f227d797ddc7279d2fcc2c7c \
--hash=sha256:18857b9e6579300be55c91c0a1cfd37d9a2cf0cabea33b88275f199eb73b8b58
# via vyral
vyral==0.1.1 \
--hash=sha256:f18adc5b9ea9057e0bbf293749383b0e2ac08d786d794c75c6e1ad414b528d67 \
--hash=sha256:f28b0c9b2bdc533821ce4e8f6369965fa07b6817bead0942bcc008fb2295dc8a
# via -r runtimes/python/requirements-server.in
85 changes: 85 additions & 0 deletions samples/Vyral.CanonicalProjectionStarter/packages.lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"version": 1,
"dependencies": {
"net10.0": {
"Microsoft.Data.Sqlite": {
"type": "Direct",
"requested": "[10.0.11, )",
"resolved": "10.0.11",
"contentHash": "7je7UELzm131GiLYc4PpZvfKXIgIyzPM+v+tjcd/nbnuWRfgcONYKzDTqJlURxwVCFsVnlpmq6y6yn4qvR8QXQ==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "10.0.11",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.12",
"SQLitePCLRaw.core": "2.1.12"
}
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "10.0.11",
"contentHash": "hubA20AGenQ4Sx0ElWaPpB8DISjXpdx463+1zOGRslsT0e/t/06ITv+pHsop8CcJ0d8PZLfgnT7juCDVD79Dkw==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.12"
}
},
"SQLite": {
"type": "Transitive",
"resolved": "3.53.4",
"contentHash": "KN7jeWqgUPeBRe1FlcpZURzxomuKKEKHmBBQfg+Nx7NkY1LjKhzHvH+3ASkNvhayESE34nMBinL9CV21JfPRJw=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "3.0.5",
"contentHash": "SW8iASIyWMrLzqabUHYQRvALhvD4ylSBsj4PgEVGwc36kQjc9xT5kSV/XQ9rU7nIpBWD+LPyX3Hlw5FzyUzGeQ==",
"dependencies": {
"SQLite": "3.53.4",
"SQLitePCLRaw.config.e_sqlite3": "3.0.5"
}
},
"SQLitePCLRaw.config.e_sqlite3": {
"type": "Transitive",
"resolved": "3.0.5",
"contentHash": "aSk8WE5tF2MybESMgtZAEyMVCAWA0nBqOMc48HFoa9UoSdtm3goDXVzNRnefeKIwE6bV9NaNXptn1F9ReMQI0Q==",
"dependencies": {
"SQLitePCLRaw.provider.e_sqlite3": "3.0.5"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "3.0.5",
"contentHash": "k81AYXXRCw3Zj8rOhyBoCsx/U97KYDFI2CSKr/ijl5BwpsW/hX/4kBiDmerFaoust8nxBwa0IHQFw8MmSHRtnQ=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "3.0.5",
"contentHash": "um8YSWduhhuskTG2bHfZrBqMNQOydfU8pcseT+cu5RivOGyoUbCrGXxgoRNTmRYw2VbMWnEZVVFcneZT/5dsBg==",
"dependencies": {
"SQLitePCLRaw.core": "3.0.5"
}
},
"System.Numerics.Tensors": {
"type": "Transitive",
"resolved": "10.0.11",
"contentHash": "4jNNt67NhCqf3bf2FN0mrsC+EH60L7Sny6poqVeiviB27Kw7TQzMmgn8HIaPc8E9EcuGusUyfeu21gLfzcBpDA=="
},
"vyral.abstractions": {
"type": "Project",
"dependencies": {
"Vyral.Primitives": "[0.2.0, )"
}
},
"vyral.local": {
"type": "Project",
"dependencies": {
"Microsoft.Data.Sqlite": "[10.0.11, )",
"SQLitePCLRaw.bundle_e_sqlite3": "[3.0.5, )",
"SQLitePCLRaw.core": "[3.0.5, )",
"System.Numerics.Tensors": "[10.0.11, )",
"Vyral.Abstractions": "[0.3.0, )"
}
},
"vyral.primitives": {
"type": "Project"
}
}
}
}
Loading
Loading