Compare commits

...

21 Commits

Author SHA1 Message Date
d965413a9d Sync chart from pieced-operator 0.1.45 2026-05-11 20:13:23 +00:00
29e4527745 Sync chart from pieced-operator 0.1.44 2026-05-11 19:25:51 +00:00
f2d5d296e2 Sync chart from pieced-operator 0.1.43 2026-05-10 20:35:06 +00:00
afc44ebbf8 Sync chart from pieced-operator 0.1.42 2026-05-10 20:16:28 +00:00
1ef1c0e456 Sync chart from pieced-operator 0.1.41 2026-05-10 19:56:48 +00:00
f182211601 Sync chart from pieced-operator 0.1.40 2026-05-10 19:23:49 +00:00
5d46d3ada0 Sync chart from pieced-operator 0.1.39 2026-05-01 20:16:26 +00:00
e98dd8b0a2 Sync chart from pieced-operator 0.1.38 2026-05-01 16:42:18 +00:00
90a9aad15d Sync chart from pieced-operator 0.1.37 2026-05-01 16:12:31 +00:00
4f4b4286dc Sync chart from pieced-operator 0.1.36 2026-05-01 09:08:18 +00:00
1cc2ec2e92 Sync chart from pieced-operator 0.1.35 2026-05-01 08:37:15 +00:00
b3cc9b0975 Sync chart from pieced-operator 0.1.34 2026-05-01 08:26:13 +00:00
a6f19e23c6 Sync chart from pieced-operator 0.1.33 2026-04-30 21:27:54 +00:00
ec41528f1e Sync chart from pieced-operator 0.1.32 2026-04-30 20:53:31 +00:00
23f16bc7a8 Sync chart from pieced-operator 0.1.31 2026-04-30 20:42:39 +00:00
229d8e5389 Sync chart from pieced-operator 0.1.30 2026-04-30 20:19:45 +00:00
69983fa321 Sync chart from pieced-operator 0.1.29 2026-04-30 20:08:59 +00:00
9c2bc1223f Sync chart from pieced-operator 0.1.28 2026-04-29 21:49:48 +00:00
a31c259909 Sync chart from pieced-operator 0.1.27 2026-04-29 21:40:33 +00:00
2230aae540 Sync chart from pieced-operator 0.1.26 2026-04-29 21:29:39 +00:00
037d4d8994 Sync chart from pieced-operator 0.1.25 2026-04-29 21:13:52 +00:00
6 changed files with 441 additions and 48 deletions

View File

@@ -1,6 +1,6 @@
apiVersion: v2 apiVersion: v2
name: pieced-operator name: pieced-operator
description: PieCed IT tenant lifecycle operator description: PieCed IT tenant lifecycle operator
version: 0.1.24 version: 0.1.45
appVersion: "0.1.24" appVersion: "0.1.45"
type: application type: application

View File

@@ -1,5 +1,18 @@
# The package catalog is deployed as a ConfigMap in the operator namespace. # The package catalog is deployed as a ConfigMap in the operator namespace.
# To update packages, edit the catalog data below and upgrade the Helm release. # To update packages, edit the catalog data below and upgrade the Helm release.
#
# Categories:
# - core — toggles platform-level OpenClaw behaviour (heartbeat, cron,
# active-memory, voice) via config_patch. No channel bindings,
# no skills.
# - channel — adds a messaging channel (Telegram, Discord, …).
# - skill — adds a ClawHub or pack: skill ref to the OpenClawInstance.
#
# Quiet hours are not exposed as a separate package — in OpenClaw they live
# under the heartbeat config (via the active-window setting and via
# HEARTBEAT.md content rules). When we expose a tenant-tunable time range
# in the portal, it will become additional fields on core-heartbeat rather
# than its own package.
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
@@ -10,6 +23,130 @@ metadata:
data: data:
catalog.yaml: | catalog.yaml: |
packages: packages:
# =====================================================================
# CORE — platform behaviour toggles. Patched into OCI config.raw via
# config_patch (deep-merged on top of the operator's safe defaults).
# =====================================================================
core-heartbeat:
name: Heartbeat (Proactive Checks)
category: core
description: >
Periodic agent run (default every 30 min) that lets the assistant
check inbox, calendar, and other configured sources and message
you proactively when something needs attention. Without this, the
assistant only responds when you message it first.
# OpenClaw 2026.x ships heartbeat ON by default (30m, or 1h on
# Anthropic OAuth) when agents.defaults.heartbeat is absent —
# see issues openclaw/openclaw#64293, #19445, #8123. The builder
# accordingly writes `every: "0m"` (the known off-switch) into
# the baseline configRaw. core-heartbeat's config_patch below
# overlays the 30m cadence on top of that. The actual checklist
# the heartbeat reads lives in workspace HEARTBEAT.md (seeded
# separately via spec.workspaceFiles); without a HEARTBEAT.md
# the heartbeat fires harmlessly and replies HEARTBEAT_OK.
#
# Quiet hours: OpenClaw supports both a config-level activeHours
# window under agents.defaults.heartbeat (skipped outside the
# window) and in-content rules inside HEARTBEAT.md. Neither is
# exposed in the portal yet — when added, they become extra
# fields on this package, not a separate core-quiet-hours
# package.
config_patch:
agents:
defaults:
heartbeat:
every: "30m"
core-cron:
name: Scheduled Tasks (Cron)
category: core
description: >
Allow the assistant to run scheduled tasks (daily briefings,
recurring reminders, periodic reports). Off by default. When
off, the agent's cron tool stays available but no scheduled
job ever fires.
# Flips the cron scheduler on. Default base configRaw sets
# cron.enabled=false (see builder.go), so this overlay only
# writes true when the package is enabled. Job storage lives on
# the tenant PVC at ~/.openclaw/cron/jobs.json by default.
config_patch:
cron:
enabled: true
core-active-memory:
name: Active Memory
category: core
description: >
Lets the assistant recall stable preferences, recurring habits,
and long-term context from past conversations during a chat.
Uses an extra sub-agent turn per inbound message to query the
memory store. Direct-message sessions only — group and channel
sessions stay deterministic. Trades a small amount of token
cost for continuity and personalisation.
# OpenClaw 2026.5.x ships Active Memory as a plugin under
# plugins.entries.active-memory with a two-gate activation model:
# (1) the plugin must be enabled, (2) the request must be an
# eligible direct-chat session. Scoped to "main" agent and
# "direct" chat types for safe-default behaviour. The recall
# model inherits the session's chat model when available; the
# modelFallback is used only when nothing else resolves and
# should be present in LiteLLM. Adjust as needed for the
# platform's default cheap model.
config_patch:
plugins:
entries:
active-memory:
enabled: true
config:
enabled: true
agents: ["main"]
allowedChatTypes: ["direct"]
modelFallback: "pieced-mini"
queryMode: "recent"
promptStyle: "balanced"
timeoutMs: 15000
maxSummaryChars: 220
persistTranscripts: false
logging: false
core-voice:
name: Voice Interaction
category: core
description: >
Speech-to-text on incoming voice notes and text-to-speech on
replies. Routed through PieCed's LiteLLM gateway so audio cost
is tracked per-tenant alongside chat.
# PHASE A: catalog entry only. No config_patch yet — toggling
# this package stores customer intent but does not change the
# OCI config. PHASE B (next iteration) wires in chatterbox-tts
# and a whisper adapter (or speaches-server) behind LiteLLM and
# adds the config_patch below, roughly:
#
# config_patch:
# tools:
# media:
# audio:
# enabled: true
# models:
# - provider: openai
# model: pieced-whisper
# apiBase: http://litellm.inference.svc:4000/v1
# messages:
# tts:
# auto: inbound
# provider: openai
# openai:
# model: pieced-tts
# voice: nova
# =====================================================================
# CHANNELS — messaging integrations. Each ships a Channels map that
# the builder copies into config.channels, env_vars for credentials,
# and bindings so messages route to the default agent.
# =====================================================================
telegram: telegram:
name: Telegram name: Telegram
category: channel category: channel
@@ -62,51 +199,218 @@ data:
2. Create app, add bot, copy token and app ID 2. Create app, add bot, copy token and app ID
3. Invite bot to server with messages scope 3. Invite bot to server with messages scope
email: # =====================================================================
name: Email (Gmail) # SKILLS — ClawHub skill installs. Operator passes each entry through
category: channel # to OpenClawInstance.spec.skills, where the OpenClaw operator's init
description: Email integration via Gmail IMAP/SMTP # container fetches it before the agent starts. Bare "<owner>/<slug>"
channels: # resolves through ClawHub by default.
email: # =====================================================================
enabled: true
settings:
provider: gmail
env_vars:
- name: EMAIL_ADDRESS
secret_key: address
vault_path_suffix: email
- name: EMAIL_APP_PASSWORD
secret_key: app-password
vault_path_suffix: email
bindings:
- match:
channel: email
egress_rules:
- host: imap.gmail.com
port: 993
- host: smtp.gmail.com
port: 465
web-search: git-cli:
name: Web Search name: Git CLI
category: skill category: skill
description: Web search via internal SearXNG description: >
Standalone git command-line operations (clone, commit, branch,
diff, log, status). For private repositories, configure
credentials in your workspace.
skills: skills:
- "pack:openclaw/skills/web-search@latest" - "openlang-cn/git-cli"
egress_rules:
- host: github.com
port: 443
- host: gitlab.com
port: 443
github:
name: GitHub (gh CLI)
category: skill
description: >
Interact with GitHub repositories via the gh CLI — issues, PRs,
CI runs, releases, gists. Requires a personal access token.
skills:
- "steipete/github"
env_vars:
- name: GH_TOKEN
secret_key: token
vault_path_suffix: github
required: true
egress_rules:
- host: api.github.com
port: 443
- host: github.com
port: 443
- host: codeload.github.com
port: 443
customer_instructions: |
1. Open https://github.com/settings/tokens
2. Generate a fine-grained personal access token with the
repo scopes you want the assistant to use.
3. Copy the token (it is shown only once).
gitea:
name: Gitea
category: skill
description: >
Interact with a Gitea instance — repositories, issues, PRs,
releases. Defaults to the PieCed-platform Gitea at
git.c5ai.ch; supply your own GITEA_URL if you host elsewhere.
skills:
- "ericxliu1990/gitea"
env_vars:
- name: GITEA_URL
default: "https://git.c5ai.ch"
- name: GITEA_TOKEN
secret_key: token
vault_path_suffix: gitea
required: true
egress_rules:
- host: git.c5ai.ch
port: 443
customer_instructions: |
1. Log in to your Gitea instance (default https://git.c5ai.ch).
2. Go to Settings → Applications → Generate New Token.
3. Grant the scopes you want the assistant to use (repo, issue,
user — minimum needed for most workflows).
4. Copy the token.
whisper-self-hosted:
name: Whisper (Self-Hosted Transcription)
category: skill
description: >
Transcribe audio files via the platform's self-hosted Whisper
ASR instance. Useful for ad-hoc transcription tasks initiated
from chat; channel-level voice intake is handled separately by
the Voice CORE feature.
skills:
- "xavjer/openclaw-self-hosted-whisper"
env_vars:
- name: WHISPER_URL
default: "http://whisper-asr.whisper-asr.svc.cluster.local:9000"
searxng-local-search:
name: Web Search (SearXNG)
category: skill
description: >
Privacy-respecting web search via the platform's internal
SearXNG instance. Search the web, images, news, and more
without external API calls or trackers.
skills:
- "noblepayne/searxng-local-search"
env_vars: env_vars:
- name: SEARXNG_URL - name: SEARXNG_URL
default: "http://searxng.searxng.svc.cluster.local:8080" default: "http://searxng.searxng.svc.cluster.local:8080"
egress_rules: []
document-processing: gog:
name: Document Processing name: Google Workspace (Gog)
category: skill category: skill
description: PDF, DOCX, spreadsheet processing description: >
Bundled access to Gmail, Calendar, Drive, Docs, Sheets, and
Contacts via Google OAuth. Setup requires a Google Cloud
project and an OAuth client. NOTE: OAuth flow is not yet
self-service in the portal — contact PieCed support for
credentials onboarding.
skills: skills:
- "pack:openclaw/skills/document-processing@latest" - "steipete/gog"
init_deps: env_vars:
apt: - name: GOG_CLIENT_ID
- pandoc secret_key: client-id
- libreoffice-writer-nogui vault_path_suffix: gog
- ffmpeg required: true
egress_rules: [] - name: GOG_CLIENT_SECRET
secret_key: client-secret
vault_path_suffix: gog
required: true
- name: GOG_REFRESH_TOKEN
secret_key: refresh-token
vault_path_suffix: gog
required: true
egress_rules:
- host: oauth2.googleapis.com
port: 443
- host: www.googleapis.com
port: 443
- host: gmail.googleapis.com
port: 443
- host: calendar.googleapis.com
port: 443
- host: drive.googleapis.com
port: 443
- host: docs.googleapis.com
port: 443
- host: sheets.googleapis.com
port: 443
- host: people.googleapis.com
port: 443
customer_instructions: |
Google Workspace integration uses OAuth and requires manual
onboarding for now. Please open a support ticket to start
the setup process — we will exchange the client credentials
and a refresh token offline, then enable this package on
your tenant.
disclaimer: >
By enabling Google Workspace integration you authorize PieCed
to access Gmail, Calendar, Drive, Docs, Sheets, and Contacts
on your behalf. Data flows through Google's APIs subject to
Google's terms.
mail:
name: Email (IMAP / SMTP)
category: skill
description: >
Read, search, and manage email via IMAP; send via SMTP. Works
with Gmail (with an app password), Outlook, Fastmail, and any
standard IMAP/SMTP host. Replaces the previous Gmail-only
channel.
skills:
- "ivangdavila/mail"
env_vars:
- name: IMAP_HOST
secret_key: imap-host
vault_path_suffix: mail
required: true
- name: IMAP_USER
secret_key: imap-user
vault_path_suffix: mail
required: true
- name: IMAP_PASS
secret_key: imap-pass
vault_path_suffix: mail
required: true
- name: SMTP_HOST
secret_key: smtp-host
vault_path_suffix: mail
required: true
- name: SMTP_USER
secret_key: smtp-user
vault_path_suffix: mail
required: true
- name: SMTP_PASS
secret_key: smtp-pass
vault_path_suffix: mail
required: true
# The mail skill connects to tenant-supplied IMAP/SMTP servers on
# ports 993 / 465 / 587. The hostnames are not known at catalog
# time, so we open these ports to "world" rather than declaring
# FQDNs. Trade-off accepted for pilot — see catalog.EgressRule
# for the rule shape and rationale.
egress_rules:
- port: 993
world: true
- port: 465
world: true
- port: 587
world: true
customer_instructions: |
1. For Gmail: enable 2-Step Verification, then create an App
Password at https://myaccount.google.com/apppasswords and
use it as both IMAP and SMTP password.
2. For Outlook/Microsoft 365 with MFA: generate an app
password under your account's security settings.
3. For other providers: refer to their IMAP/SMTP documentation
for host names and ports.
4. Typical IMAP_HOST values: imap.gmail.com, outlook.office365.com.
5. Typical SMTP_HOST values: smtp.gmail.com, smtp.office365.com.
disclaimer: >
The assistant gains read/write access to the mailbox you
configure. Use a dedicated address rather than a personal
inbox if you want to limit scope.

View File

@@ -87,6 +87,18 @@ spec:
suspend: suspend:
type: boolean type: boolean
description: Stops reconciliation without deleting resources. description: Stops reconciliation without deleting resources.
openClawImage:
type: object
description: >
Per-tenant override for the OpenClaw container image
tag. When unset, the operator uses the platform
default from the pieced-openclaw-config ConfigMap.
Set by platform admins via the portal; customer-
facing onboarding does not expose this field.
properties:
tag:
type: string
description: Image tag (e.g. "2026.4.22").
status: status:
type: object type: object
properties: properties:
@@ -123,6 +135,25 @@ spec:
type: array type: array
items: items:
type: string type: string
suspendedAt:
type: string
format: date-time
warnings:
type: array
items:
type: object
required:
- source
properties:
source:
type: string
reason:
type: string
message:
type: string
since:
type: string
format: date-time
observedGeneration: observedGeneration:
type: integer type: integer
format: int64 format: int64

View File

@@ -0,0 +1,25 @@
{{/*
Platform-wide default OpenClaw image tag. Used by the operator when a
PiecedTenant has no explicit `spec.openClawImage.tag` override.
Tag-only by design — see internal/openclawconfig/loader.go for
rationale (single image-selector field avoids SSA field-ownership
ambiguity). For reproducibility-critical deployments, pin by using
an immutable release tag.
If `defaultTag` is empty (or this ConfigMap doesn't exist), the
operator falls back to a hardcoded built-in version.
Tenants without an `openClawImage` override automatically follow
changes to this ConfigMap on the next reconcile — the operator
watches it and re-enqueues affected tenants.
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: pieced-openclaw-config
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: pieced-operator
data:
defaultTag: {{ .Values.openClaw.defaultTag | quote }}

View File

@@ -8,9 +8,17 @@ metadata:
app.kubernetes.io/name: pieced-operator app.kubernetes.io/name: pieced-operator
rules: rules:
# --- PiecedTenant CRD --- # --- PiecedTenant CRD ---
# `delete` is required so the operator can self-initiate the post-
# 60-day cleanup of suspended tenants (Bug 37b). Without it, the
# `r.Delete(ctx, tenant)` call in the suspend block fails with a
# 403 every reconcile cycle while the tenant sits past its
# retention window. Until then this verb wasn't strictly needed —
# the customer/portal initiated CR deletes, and the operator's
# finalizer ran cleanup; only with operator-initiated deletion did
# the missing verb become a problem.
- apiGroups: ["pieced.ch"] - apiGroups: ["pieced.ch"]
resources: ["piecedtenants"] resources: ["piecedtenants"]
verbs: ["get", "list", "watch", "update", "patch"] verbs: ["get", "list", "watch", "update", "patch", "delete"]
- apiGroups: ["pieced.ch"] - apiGroups: ["pieced.ch"]
resources: ["piecedtenants/status"] resources: ["piecedtenants/status"]
verbs: ["get", "update", "patch"] verbs: ["get", "update", "patch"]
@@ -34,29 +42,34 @@ rules:
verbs: ["create", "patch"] verbs: ["create", "patch"]
# --- Capsule Tenant --- # --- Capsule Tenant ---
# `patch` is required for server-side apply (SSA) — controller-runtime's
# `client.Apply` uses HTTP PATCH with content-type application/apply-patch+yaml.
# We keep `update` for backwards-compat in case any code path still does
# replace-style writes (currently none). Same applies to all unstructured
# resources below.
- apiGroups: ["capsule.clastix.io"] - apiGroups: ["capsule.clastix.io"]
resources: ["tenants"] resources: ["tenants"]
verbs: ["get", "list", "watch", "create", "update", "delete"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# --- ESO SecretStore --- # --- ESO SecretStore ---
- apiGroups: ["external-secrets.io"] - apiGroups: ["external-secrets.io"]
resources: ["secretstores"] resources: ["secretstores"]
verbs: ["get", "list", "watch", "create", "update", "delete"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# --- ESO ExternalSecret --- # --- ESO ExternalSecret ---
- apiGroups: ["external-secrets.io"] - apiGroups: ["external-secrets.io"]
resources: ["externalsecrets"] resources: ["externalsecrets"]
verbs: ["get", "list", "watch", "create", "update", "delete"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# --- Cilium CiliumNetworkPolicy --- # --- Cilium CiliumNetworkPolicy ---
- apiGroups: ["cilium.io"] - apiGroups: ["cilium.io"]
resources: ["ciliumnetworkpolicies"] resources: ["ciliumnetworkpolicies"]
verbs: ["get", "list", "watch", "create", "update", "delete"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# --- OpenClaw OpenClawInstance --- # --- OpenClaw OpenClawInstance ---
- apiGroups: ["openclaw.rocks"] - apiGroups: ["openclaw.rocks"]
resources: ["openclawinstances"] resources: ["openclawinstances"]
verbs: ["get", "list", "watch", "create", "update", "delete"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# --- Leader election (coordination) --- # --- Leader election (coordination) ---
- apiGroups: ["coordination.k8s.io"] - apiGroups: ["coordination.k8s.io"]

View File

@@ -1,6 +1,6 @@
image: image:
repository: registry.c5ai.ch/pieced/pieced-operator repository: registry.c5ai.ch/pieced/pieced-operator
tag: "0.1.24" tag: "0.1.45"
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
imagePullSecrets: imagePullSecrets:
@@ -56,3 +56,23 @@ serviceAccount:
# Network policy — restrict operator egress to only what it needs # Network policy — restrict operator egress to only what it needs
networkPolicy: networkPolicy:
enabled: true enabled: true
# OpenClaw image default (Feature: per-tenant version overrides).
#
# Materialised as the `pieced-openclaw-config` ConfigMap, which the
# operator reads on every reconcile. Per-tenant overrides set via the
# portal (PiecedTenant.spec.openClawImage.tag) take precedence over
# this default for the affected tenants.
#
# We support tag-only (not digest) by design — a single image-selector
# field avoids SSA field-ownership ambiguity when switching values,
# and the downstream OpenClaw operator handles a tag-only image spec
# unambiguously. For reproducibility-critical deployments, pin by
# using an immutable release tag.
#
# Empty defaultTag falls back to the operator's built-in version.
# Admins can edit this value at runtime via the portal admin UI;
# the resulting ConfigMap edits trigger reconciles for every tenant
# that doesn't have its own override.
openClaw:
defaultTag: "2026.4.22"