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
4 changes: 2 additions & 2 deletions .github/workflows/build-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
podman run --rm opencode-dev-amd64 gaze --version
podman run --rm opencode-dev-amd64 go version
podman run --rm opencode-dev-amd64 golangci-lint --version
podman run --rm opencode-dev-amd64 govulncheck -version
podman run --rm --entrypoint which opencode-dev-amd64 govulncheck
podman run --rm opencode-dev-amd64 node --version
podman run --rm opencode-dev-amd64 npm --version
podman run --rm opencode-dev-amd64 git --version
Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
podman run --rm opencode-dev-arm64 gaze --version
podman run --rm opencode-dev-arm64 go version
podman run --rm opencode-dev-arm64 golangci-lint --version
podman run --rm opencode-dev-arm64 govulncheck -version
podman run --rm --entrypoint which opencode-dev-arm64 govulncheck
podman run --rm opencode-dev-arm64 node --version
podman run --rm opencode-dev-arm64 npm --version
podman run --rm opencode-dev-arm64 git --version
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,41 @@ which uses the Universal Developer Image and installs tools via
**Security properties**: Workspace-level isolation managed by Eclipse
Che. Resource limits set in devfile. No secrets in image.

### CDE Endpoints

Both devfiles expose public endpoints for agent-built applications so
engineers can demo web apps and APIs directly from the Che workspace:

| Endpoint | Port | Exposure | Use Case |
|----------|------|----------|----------|
| `opencode-server` | 4096 | internal | OpenCode server (accessed via `opencode attach`) |
| `demo-http` | 3000 | public | Agent-built web apps (Next.js, Vite, etc.) |
| `demo-api` | 8080 | public | Agent-built API servers (Go, Spring, etc.) |
| `demo-alt` | 8443 | public | Alternate services or HTTPS endpoints |

Che manages ingress and authentication for public endpoints — each gets
a unique URL accessible from outside the workspace. If the agent builds
on a port not listed here, add a temporary endpoint via the Che UI.

### Ollama in CDE

The `DEWEY_EMBEDDING_ENDPOINT` environment variable controls Dewey's
connection to Ollama for semantic embeddings. The default is empty in
the devfiles, which means Dewey uses keyword-only search (fully
functional, no embeddings).

Configure per environment:

| Environment | Value | How to Set |
|-------------|-------|------------|
| **Local Podman** | `http://host.containers.internal:11434` | Set in `podman-compose.yml` or `-e` flag (already configured) |
| **CDE / Kubernetes** | Ollama service URL (e.g., `http://ollama.my-namespace:11434`) | Che user preferences or K8s ConfigMap/Secret |
| **No Ollama** | `""` (empty) | Default in devfiles — keyword search works, semantic search disabled |

Ollama is never installed inside the container (Constitution I). When
the endpoint is empty or unreachable, the container starts normally and
Dewey falls back to keyword search.

## Security Model

These constraints are non-negotiable:
Expand Down
30 changes: 28 additions & 2 deletions devfile-dynamic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ components:
cpuLimit: "4"
mountSources: true
env:
# Ollama endpoint for Dewey semantic search. Empty = keyword-only.
# Local Podman: http://host.containers.internal:11434
# CDE on K8s: set via Che user preferences or K8s secret
- name: DEWEY_EMBEDDING_ENDPOINT
value: "http://host.containers.internal:11434"
value: ""
- name: GOPATH
value: "/home/user/go"
- name: PATH
Expand All @@ -31,6 +34,18 @@ components:
- name: opencode-server
targetPort: 4096
exposure: internal
- name: demo-http
targetPort: 3000
exposure: public
protocol: https
- name: demo-api
targetPort: 8080
exposure: public
protocol: https
- name: demo-alt
targetPort: 8443
exposure: public
protocol: https

commands:
- id: install-tools
Expand Down Expand Up @@ -61,6 +76,17 @@ commands:
commandLine: "uf init"
workingDir: /projects

# Composite command enforces sequential execution order.
# postStart events are NOT guaranteed sequential per the
# devfile spec — a composite with parallel: false is required.
- id: post-start-sequence
composite:
commands:
- install-tools
- init-workspace
- start-server
parallel: false

events:
postStart:
- install-tools
- post-start-sequence
31 changes: 30 additions & 1 deletion devfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,27 @@ components:
cpuLimit: "4"
mountSources: true
env:
# Ollama endpoint for Dewey semantic search. Empty = keyword-only.
# Local Podman: http://host.containers.internal:11434
# CDE on K8s: set via Che user preferences or K8s secret
- name: DEWEY_EMBEDDING_ENDPOINT
value: "http://host.containers.internal:11434"
value: ""
endpoints:
- name: opencode-server
targetPort: 4096
exposure: internal
- name: demo-http
targetPort: 3000
exposure: public
protocol: https
- name: demo-api
targetPort: 8080
exposure: public
protocol: https
- name: demo-alt
targetPort: 8443
exposure: public
protocol: https

commands:
- id: start-server
Expand All @@ -39,3 +54,17 @@ commands:
component: opencode-dev
commandLine: "uf init"
workingDir: /projects

# Composite command enforces sequential execution order.
# postStart events are NOT guaranteed sequential per the
# devfile spec — a composite with parallel: false is required.
- id: post-start-sequence
composite:
commands:
- init-workspace
- start-server
parallel: false

events:
postStart:
- post-start-sequence
2 changes: 2 additions & 0 deletions openspec/changes/cde-endpoints/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: unbound-force
created: 2026-04-13
82 changes: 82 additions & 0 deletions openspec/changes/cde-endpoints/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
## Context

The CDE devfiles expose only port 4096 (OpenCode server, internal),
hardcode `host.containers.internal` for Ollama (Podman-only hostname),
and don't auto-start the OpenCode server. These gaps prevent the
iterative demo loop in Eclipse Che / Dev Spaces.

See proposal.md for full motivation and constitution alignment.

## Goals / Non-Goals

### Goals
- Expose demo endpoints (3000, 8080, 8443) for agent-built apps
- Make Ollama endpoint configurable (empty default, per-env setup)
- Auto-start OpenCode server via postStart event
- Document CDE endpoint and Ollama configuration in README

### Non-Goals
- Installing Ollama inside the container (Constitution II violation)
- Changing the Containerfile or base image
- Adding credential injection (tracked in Issue #4)
- Changing the OpenCode server port or exposure level

## Decisions

### D1: Demo endpoint port selection (3000, 8080, 8443)

**Decision**: Expose ports 3000 (HTTP), 8080 (API), and 8443
(HTTPS/alt) as public endpoints.

**Rationale**: These are the most common default ports for web
frameworks (Next.js/Vite → 3000, Go/Spring → 8080, HTTPS → 8443).
Covering these three handles the majority of agent-built demo apps
without requiring devfile edits. If an agent builds on a non-standard
port, the engineer can add a temporary endpoint via Che's UI.

### D2: Empty DEWEY_EMBEDDING_ENDPOINT default

**Decision**: Set `DEWEY_EMBEDDING_ENDPOINT` to empty string in
devfiles. Document per-environment configuration.

**Rationale**: An empty value causes Dewey to skip embeddings
gracefully (keyword search still works). This is better than a
hostname that fails to resolve in K8s, which causes confusing
connection timeouts. The engineer sets the correct value for their
environment via Che user preferences or K8s secret.

For local Podman, the value is still set in podman-compose.yml and
the Containerfile ENV — those are not changed.

### D3: postStart event ordering

**Decision**: Add `start-server` after `init-workspace` in
`events.postStart`.

**Rationale**: `init-workspace` runs `uf init` which sets up the
project. The OpenCode server should start after initialization so
it can discover the project configuration. For the dynamic devfile,
`install-tools` must run before both.

Ordering:
- **devfile.yaml**: `init-workspace` → `start-server`
- **devfile-dynamic.yaml**: `install-tools` → `init-workspace` → `start-server`

### D4: Keep opencode-server as internal

**Decision**: The OpenCode server endpoint (4096) stays
`exposure: internal`.

**Rationale**: The OpenCode server is accessed via `opencode attach`,
not via browser. Making it public would expose it to anyone with the
Che ingress URL. Per Constitution II (Security Through Isolation),
internal exposure is appropriate.

## Risks / Trade-offs

| Risk | Impact | Mitigation |
|------|--------|------------|
| Port conflicts if agent uses 3000/8080/8443 for something else | Low — unlikely, standard ports | Engineer can modify devfile |
| Empty Ollama endpoint means no semantic search by default in CDE | Medium — keyword search still works | Document setup steps clearly in README |
| postStart `start-server` may fail if OpenCode binary missing | Low — only affects broken images | entrypoint.sh already handles gracefully |
| Adding 3 public endpoints increases attack surface in CDE | Low — Che manages ingress + auth | Standard practice for Che workspaces |
98 changes: 98 additions & 0 deletions openspec/changes/cde-endpoints/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
## Why

The CDE devfiles (devfile.yaml and devfile-dynamic.yaml) have three
gaps that prevent the full demo workflow in Eclipse Che / Dev Spaces:

1. **Only port 4096 exposed** — engineers cannot demo web apps or
APIs built by the agent because no public endpoints exist for
common application ports (3000, 8080, 8443).

2. **Ollama endpoint uses `host.containers.internal`** — this
hostname is Podman-specific and does not resolve in Kubernetes
where Che/Dev Spaces runs. Dewey semantic search fails silently.

3. **No auto-start for OpenCode server** — the `start-server`
command exists but is not in `events.postStart`. Engineers must
manually start it after workspace creation.

Ref: [Issue #3](https://github.com/unbound-force/containerfile/issues/3),
[Discussion #88 CDE update](https://github.com/orgs/unbound-force/discussions/88#discussioncomment-16545846),
[unbound-force#95](https://github.com/unbound-force/unbound-force/issues/95).

## What Changes

### devfile.yaml + devfile-dynamic.yaml

- Add demo endpoints for agent-built applications (ports 3000,
8080, 8443) with `exposure: public`.
- Replace hardcoded `host.containers.internal` Ollama endpoint
with an empty default. Document how to configure per environment.
- Add `start-server` to `events.postStart` so OpenCode starts
automatically.

### README.md

- Document the demo endpoints and their intended use.
- Add Ollama configuration guidance for CDE vs local Podman.

## Capabilities

### New Capabilities
- `demo-http`: Public endpoint on port 3000 for agent-built web apps
- `demo-api`: Public endpoint on port 8080 for agent-built APIs
- `demo-alt`: Public endpoint on port 8443 for alternate services
- Auto-start OpenCode server on workspace creation

### Modified Capabilities
- `DEWEY_EMBEDDING_ENDPOINT`: Changed from hardcoded Podman hostname
to empty default with per-environment configuration guidance
- `opencode-server` endpoint: Unchanged (port 4096, internal)

### Removed Capabilities
- None

## Impact

- **devfile.yaml**: 3 new endpoint blocks, env var change, postStart event
- **devfile-dynamic.yaml**: Same changes as devfile.yaml
- **README.md**: New "CDE Endpoints" and "Ollama in CDE" sections
- **entrypoint.sh**: No changes needed — already handles missing Ollama gracefully
- **Containerfile / Containerfile.base**: No changes — endpoints are devfile-level config

## Constitution Alignment

Assessed against the containerfile project constitution (v1.0.0),
which extends the Unbound Force org constitution (v1.1.0).

### I. Composability First

**Assessment**: PASS

Demo endpoints are additive — they expose ports that may or may not
be used. The OpenCode server endpoint remains unchanged. Making
`DEWEY_EMBEDDING_ENDPOINT` empty by default improves composability:
the container starts without requiring any host service, and Ollama
can be provided when available.

### II. Security Through Isolation

**Assessment**: PASS

Demo endpoints use `exposure: public` which is appropriate for CDE
(Che manages ingress and authentication). No secrets are added to
the devfile. The `opencode-server` endpoint stays `internal`. No
changes to the container image or security model.

### III. Reproducible Builds

**Assessment**: N/A

No Containerfile or CI workflow changes. Only devfile YAML and
documentation are modified.

### IV. Executable Truth

**Assessment**: PASS

README documentation will be updated to match the new devfile
configuration. No stale documentation will remain.
Loading
Loading