Compare commits

..
Author SHA1 Message Date
aios c06a23f4f8 docs(ingress): archive cnnetmkt wildcard certificate rollout 2026-07-06 16:25:52 +08:00
aios 568c283aff fix(ingress): switch cnnetmkt to wildcard certificate 2026-07-06 16:24:28 +08:00
aios 87f9150806 chore(ingress): add SSL ingress parallel validator 2026-07-06 15:50:27 +08:00
aios 14fd6ee5c5 docs(ingress): record cnnetmkt SSL ingress status 2026-07-06 15:49:04 +08:00
aios b9328d4161 fix(ingress): add g.cnnetmkt.top GitOps alias 2026-07-06 15:48:12 +08:00
aios d8ae7ee6f6 docs(gitops): finalize V1R1C0 online baseline acceptance 2026-07-06 15:16:03 +08:00
aios 2ae60299b7 chore(gitops): archive final route and Gitea probes 2026-07-06 15:15:55 +08:00
aios c6b172dce7 chore(gitops): archive V1R1C0 migration operation scripts 2026-07-06 15:15:42 +08:00
aios d3cfef4147 docs(gitops): finalize V1R1C0 online baseline acceptance 2026-07-06 15:13:44 +08:00
aios 7abf9f7734 docs(gitops): finalize V1R1C0 online baseline acceptance 2026-07-06 15:13:02 +08:00
aios 45dd78ec79 feat(gitops): add nginx short links and webhook endpoint 2026-07-06 15:04:16 +08:00
aios 29f3c1a327 chore(gitops): add binary Gitea deployment manifests 2026-07-06 14:56:02 +08:00
aios a5232f8f6d fix(gitops): align baseline tag and secret scan 2026-07-06 14:53:20 +08:00
aios 6798e0fbf5 fix(gitops): sanitize parallel agent UAT secret handling 2026-07-06 14:52:01 +08:00
aios 9436945487 chore(gitops): add V1R1C0 runtime API and Gitea deployment manifests 2026-07-06 14:50:05 +08:00
aios 71cf9ac60d chore(gitops): add Hermes parallel agent runner 2026-07-06 14:50:05 +08:00
aios 0219bcdd86 chore(gitops): add V1R1C0 runtime API and Gitea deployment manifests 2026-07-06 14:46:03 +08:00
28 changed files with 2212 additions and 4 deletions
+19 -1
View File
@@ -51,7 +51,7 @@ def seed_base_models():
pid = 'provider.openai' if m['provider']=='openai' else 'provider.one-api'
exec_sql('''INSERT OR IGNORE INTO llm_models(id,provider_id,owner_username,model_name,display_name,context_window,input_modalities,output_modalities,supports_tools,supports_vision,supports_reasoning,cost_tier,is_base,scope,status,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', (m['id'], pid, 'system', m['model'], m['display'], m['context'], '["text"]', '["text"]', m['tools'], m['vision'], m['reasoning'], m['tier'], 1, 'global', 'active', now(), now()))
if not one('SELECT * FROM gitops_baseline WHERE id=?', ('current',)):
exec_sql('INSERT INTO gitops_baseline(id,active_version,active_tag,source_package,entry,update_mode,status,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?)', ('current','V1R1C0','V1R1C0','AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706',ENTRY,'git_patch_only','active',now(),now()))
exec_sql('INSERT INTO gitops_baseline(id,active_version,active_tag,source_package,entry,update_mode,status,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?)', ('current','V1R1C0','V1R1C0-baseline-20260706','AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip',ENTRY,'git_patch_only','active',now(),now()))
if not one('SELECT * FROM gitops_versions WHERE version=?', ('V1R1C0',)):
exec_sql('INSERT INTO gitops_versions(version,tag,level,summary,status,created_by,created_at) VALUES(?,?,?,?,?,?,?)', ('V1R1C0','V1R1C0','R','MultiUser runtime selector + GitOps + custom LLM priority registry','ready','system',now()))
@@ -127,6 +127,8 @@ class Handler(BaseHTTPRequestHandler):
body = '<h2>Base Models</h2>'+self.table([m for m in model_visible_to(username) if int(m.get('is_base') or 0)==1]); body += '<h2>Custom Models</h2>'+self.table([m for m in model_visible_to(username) if int(m.get('is_base') or 0)==0]); body += '<h2>Priority</h2>'+self.table(priority_for(username)); self.send_html('Model Registry', body); return
if path in ('/api/runtime/status','/run'):
data = rows('SELECT * FROM runtime_instances ORDER BY created_at DESC LIMIT 100'); self.send_html('Runtime', self.table(data)) if path == '/run' else self.send_json(data); return
if path in ('/hook','/api/hook'):
self.send_html('Git Webhook', '<pre>'+esc(json.dumps({'status':'ready','endpoint':'/hook/git','version':'V1R1C0'}, ensure_ascii=False, indent=2))+'</pre>'); return
if path == '/api/audit': self.send_json(rows('SELECT * FROM model_audit_logs ORDER BY created_at DESC LIMIT 200')); return
self.send_json({'error':'not_found','path':path},404)
except Exception as e: self.send_json({'error':str(e)},500)
@@ -236,6 +238,22 @@ class Handler(BaseHTTPRequestHandler):
elif '模型' in text and ('添加' in text or '新增' in text or 'add' in text.lower()): intent='add_custom_model'; plan=['validate provider','store api key as secret_ref','call /api/model/custom/add']
elif 'patch' in text.lower() or '补丁' in text: intent='create_patch'; plan=['create patch branch','commit patch metadata','run tests']
self.send_json({'intent':intent,'action_plan':plan,'execute':False,'safety_check':'V-level changes require owner approval'}); return
if path in ('/hook/git','/api/hook/git'):
event_id = uid('hook')
event_file = ROOT / 'artifacts' / 'git-webhook-events.jsonl'
event_file.parent.mkdir(parents=True, exist_ok=True)
event = {
'id': event_id,
'received_at': now(),
'event': self.headers.get('X-Gitea-Event') or self.headers.get('X-GitHub-Event') or data.get('event') or 'unknown',
'ref': data.get('ref'),
'repository': (data.get('repository') or {}).get('full_name') if isinstance(data.get('repository'), dict) else data.get('repository'),
}
with event_file.open('a', encoding='utf-8') as fh:
fh.write(json.dumps(event, ensure_ascii=False) + '\n')
smoke = subprocess.run(['bash','scripts/package_contract_check_v1r1c0.sh'], cwd=str(WORKSPACE), text=True, capture_output=True, timeout=120)
audit('webhook','git_event',event_id,{'event':event,'smoke_code':smoke.returncode})
self.send_json({'status':'accepted' if smoke.returncode == 0 else 'smoke_failed','id':event_id,'event':event,'smoke':{'code':smoke.returncode,'stdout':smoke.stdout[-2000:],'stderr':smoke.stderr[-2000:]}}); return
self.send_json({'error':'not_found','path':path},404)
except Exception as e: self.send_json({'error':str(e)},500)
+22 -2
View File
@@ -1,7 +1,7 @@
{
"active_version": "V1R1C0",
"active_tag": "V1R1C0-baseline-20260706",
"mode": "gitops-online-baseline",
"mode": "gitops-online",
"version_policy": "VxRxCx",
"update_mode": "git_patch_only",
"zip_update_deprecated": true,
@@ -24,5 +24,25 @@
"user_model_priority": true,
"chatgpt_rw": true,
"codex_rw": true
}
},
"version": "V1R1C0",
"baseline_tag": "V1R1C0-baseline-20260706",
"source": "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
"source_package": "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
"zip_update_mode": "deprecated",
"chatgpt_access": true,
"codex_access": true,
"git_url": "https://cnnetmkt.top/git/aios/aios-v23.git",
"short_links": [
"/git",
"/base",
"/ver",
"/diff",
"/patch",
"/model",
"/run",
"/api",
"/hook"
],
"updated_at": "2026-07-06T07:16:01.842497+00:00"
}
+17
View File
@@ -0,0 +1,17 @@
[Unit]
Description=AIOS GitOps Gitea
After=network.target
[Service]
Type=simple
User=aiman
Group=aiman
WorkingDirectory=/data/aios-gitops/runtime/gitea-bin
ExecStart=/data/aios-gitops/runtime/bin/gitea web --config /data/aios-gitops/runtime/gitea-bin/custom/conf/app.ini
Restart=always
RestartSec=3
Environment=USER=aiman
Environment=HOME=/home/aiman
[Install]
WantedBy=multi-user.target
+38
View File
@@ -0,0 +1,38 @@
APP_NAME = AIOS GitOps
RUN_USER = aiman
WORK_PATH = /data/aios-gitops/runtime/gitea-bin
[server]
PROTOCOL = http
HTTP_ADDR = 127.0.0.1
HTTP_PORT = 3000
DOMAIN = cnnetmkt.top
ROOT_URL = https://cnnetmkt.top/git/
SERVE_FROM_SUB_PATH = true
DISABLE_SSH = true
OFFLINE_MODE = false
[database]
DB_TYPE = sqlite3
PATH = /data/aios-gitops/runtime/gitea-bin/data/gitea.db
[repository]
ROOT = /data/aios-gitops/runtime/gitea-bin/data/repositories
DEFAULT_BRANCH = main
[security]
INSTALL_LOCK = true
SECRET_KEY = __SECRET_KEY__
INTERNAL_TOKEN = __INTERNAL_TOKEN__
[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = false
[webhook]
ALLOWED_HOST_LIST = *
[log]
MODE = console
LEVEL = Info
ROOT_PATH = /data/aios-gitops/runtime/gitea-bin/log
+22
View File
@@ -0,0 +1,22 @@
services:
gitea:
image: gitea/gitea:1.22
container_name: aios-gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__DOMAIN=cnnetmkt.top
- GITEA__server__ROOT_URL=https://cnnetmkt.top/git/
- GITEA__server__SERVE_FROM_SUB_PATH=true
- GITEA__server__HTTP_PORT=3000
- GITEA__server__SSH_DOMAIN=cnnetmkt.top
- GITEA__server__SSH_PORT=2222
- GITEA__service__DISABLE_REGISTRATION=true
- GITEA__webhook__ALLOWED_HOST_LIST=*
- GITEA__database__DB_TYPE=sqlite3
volumes:
- /data/aios-gitops/runtime/gitea:/data
ports:
- "127.0.0.1:3000:3000"
- "127.0.0.1:2222:22"
+42
View File
@@ -0,0 +1,42 @@
# BEGIN AIOS V1R1C0 GitOps short links
location = /git { return 302 /git/; }
location /git/ {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /git;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
}
location = /api { return 302 /api/; }
location /api/ {
proxy_pass http://127.0.0.1:18890/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location = /base { proxy_pass http://127.0.0.1:18890/base; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /ver { proxy_pass http://127.0.0.1:18890/ver; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /diff { proxy_pass http://127.0.0.1:18890/diff; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /patch { proxy_pass http://127.0.0.1:18890/patch; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /model { proxy_pass http://127.0.0.1:18890/model; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /run { proxy_pass http://127.0.0.1:18890/run; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /hook { proxy_pass http://127.0.0.1:18890/hook; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location /hook/ {
proxy_pass http://127.0.0.1:18890/hook/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# END AIOS V1R1C0 GitOps short links
@@ -0,0 +1,12 @@
# cnnetmkt wildcard certificate
generated_at=2026-07-06T16:24:28+08:00
issuer=Let's Encrypt via lego DNS-01 Huawei Cloud
domains=cnnetmkt.top,*.cnnetmkt.top
live_dir=/etc/letsencrypt/live/cnnetmkt-wildcard
nginx_sites=/etc/nginx/sites-available/aios-user-portal.conf,/etc/nginx/sites-available/g-cnnetmkt-gitea.conf
renew_service=cnnetmkt-wildcard-renew.service
renew_timer=cnnetmkt-wildcard-renew.timer
secret_env=/etc/letsencrypt/huaweicloud-cnnetmkt.env
backup_dir=/data/aios-gitops/backups/nginx-wildcard-20260706-162202
status=issued
+52
View File
@@ -0,0 +1,52 @@
# AIOS GitOps alias for https://g.cnnetmkt.top/
# Note: this server block intentionally keeps /git/ as the Gitea app prefix,
# matching the current Gitea ROOT_URL and avoiding a disruptive app.ini rewrite.
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name g.cnnetmkt.top;
access_log /var/log/nginx/aios-g-cnnetmkt.access.log;
error_log /var/log/nginx/aios-g-cnnetmkt.error.log;
ssl_certificate /etc/letsencrypt/live/cnnetmkt-wildcard/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cnnetmkt-wildcard/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location = / {
return 302 /git/;
}
location = /git {
return 302 /git/;
}
location /git/ {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /git;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
}
}
server {
listen 80;
listen [::]:80;
server_name g.cnnetmkt.top;
location = / {
return 302 https://$host/git/;
}
location / {
return 301 https://$host$request_uri;
}
}
@@ -0,0 +1,20 @@
[Unit]
Description=AIOS V1R1C0 GitOps Model API
After=network.target
[Service]
Type=simple
User=aiman
Group=aiman
Environment=AIOS_GITOPS_ROOT=/data/aios-gitops
Environment=AIOS_GITOPS_WORKSPACE=/data/aios-gitops/workspace
Environment=AIOS_GITOPS_DB=/data/aios-gitops/runtime/gitops_model.sqlite3
Environment=AIOS_GITOPS_TOKEN_FILE=/data/aios-gitops/runtime/secrets/gitops.tokens
Environment=AIOS_GITOPS_HOST=127.0.0.1
Environment=AIOS_GITOPS_PORT=18890
ExecStart=/usr/bin/python3 /data/aios-gitops/workspace/active-runtime/app/aios_gitops_model_api.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
+83
View File
@@ -0,0 +1,83 @@
# cnnetmkt SSL ingress status
generated_at=2026-07-06T15:48:12+08:00
g_route_status=installed
certbot_status=issued-g-user-portal
apex_dns_status=blocked_until_cnnetmkt.top_has_A_record_to_1.95.164.183
wildcard_status=blocked_until_dns01_provider_credentials_available
backup_dir=/data/aios-gitops/backups/nginx-g-cnnetmkt-20260706-154743
tracked_nginx=/data/aios-gitops/workspace/deploy/nginx/g-cnnetmkt-gitea-server.conf
## validation
### g.cnnetmkt.top
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 06 Jul 2026 07:48:12 GMT
Content-Type: text/html
Content-Length: 154
Location: https://g.cnnetmkt.top/git/
Connection: keep-alive
<title>302 Found
subject=CN = user.cnnetmkt.top
issuer=C = US, O = Let's Encrypt, CN = YE2
notBefore=Jul 6 06:49:39 2026 GMT
notAfter=Oct 4 06:49:38 2026 GMT
X509v3 Subject Alternative Name:
DNS:g.cnnetmkt.top, DNS:portal.cnnetmkt.top, DNS:user.cnnetmkt.top
### cnnetmkt.top
HTTP/1.1 302 Found
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 06 Jul 2026 07:48:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Location: /portal/login/
X-Request-ID: 7c649abe-a2de-4b3e-87fe-325f4297738f
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
subject=CN = user.cnnetmkt.top
issuer=C = US, O = Let's Encrypt, CN = YE2
notBefore=Jul 6 06:49:39 2026 GMT
notAfter=Oct 4 06:49:38 2026 GMT
X509v3 Subject Alternative Name:
DNS:g.cnnetmkt.top, DNS:portal.cnnetmkt.top, DNS:user.cnnetmkt.top
### user.cnnetmkt.top
HTTP/1.1 302 Found
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 06 Jul 2026 07:48:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Location: /portal/login/
X-Request-ID: e3d70907-1ab7-456c-a725-7cb60647514d
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
subject=CN = user.cnnetmkt.top
issuer=C = US, O = Let's Encrypt, CN = YE2
notBefore=Jul 6 06:49:39 2026 GMT
notAfter=Oct 4 06:49:38 2026 GMT
X509v3 Subject Alternative Name:
DNS:g.cnnetmkt.top, DNS:portal.cnnetmkt.top, DNS:user.cnnetmkt.top
## certbot
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: user.cnnetmkt.top
Serial Number: 529feebc03b37f2866c25b1465f37e14565
Key Type: ECDSA
Domains: user.cnnetmkt.top g.cnnetmkt.top portal.cnnetmkt.top
Expiry Date: 2026-10-04 06:49:38+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/user.cnnetmkt.top/fullchain.pem
Private Key Path: /etc/letsencrypt/live/user.cnnetmkt.top/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+28
View File
@@ -0,0 +1,28 @@
# CNNETMKT wildcard certificate status
generated_at=2026-07-06T16:24:28+08:00
status=issued
staging_status=ok
dns_provider=huaweicloud
secret_storage=/etc/letsencrypt/huaweicloud-cnnetmkt.env
certificate_live_dir=/etc/letsencrypt/live/cnnetmkt-wildcard
nginx_status=loaded
backup_dir=/data/aios-gitops/backups/nginx-wildcard-20260706-162202
renew_timer=cnnetmkt-wildcard-renew.timer
## certificate
subject=CN = *.cnnetmkt.top
issuer=C = US, O = Let's Encrypt, CN = YE2
notBefore=Jul 6 07:25:55 2026 GMT
notAfter=Oct 4 07:25:54 2026 GMT
X509v3 Subject Alternative Name:
DNS:*.cnnetmkt.top, DNS:cnnetmkt.top
## routes
- https://cnnetmkt.top/
- https://cnnetmkt.top/git/
- https://g.cnnetmkt.top/
- https://g.cnnetmkt.top/git/
- https://user.cnnetmkt.top/
@@ -0,0 +1,48 @@
# AIOS V1R1C0 Online Baseline Acceptance
AIOS_V1R1C0_ONLINE_BASELINE_STATUS=PARTIAL
DOMAIN=https://cnnetmkt.top
SHORT_LINKS=/git,/base,/ver,/diff,/patch,/model,/run,/api,/hook
PROXY=NGINX_TEMP (NPM_NOT_RUNNING)
GIT_URL=https://cnnetmkt.top/git/aios/aios-v23.git
BASELINE_VERSION=V1R1C0
BASELINE_TAG=V1R1C0-baseline-20260706
WORKSPACE=/data/aios-gitops/workspace
WEBOPS_REUSED=YES
CASDOOR_REUSED=PARTIAL
OPENCLAW_REUSED=PARTIAL
HERMES_REUSED=YES
ONE_API_REUSED=YES
GITEA_REUSED=NEW
CUSTOM_LLM_STATUS=OK
MODEL_PRIORITY_STATUS=OK
RUNTIME_SELECTOR_STATUS=OK
ACCEPTANCE_REPORT=/data/aios-gitops/artifacts/AIOS_V1R1C0_ONLINE_BASELINE_ACCEPTANCE.md
KNOWN_ISSUES=NPM is not running on this host, so system nginx currently serves the short links; OpenClaw gateway is active but native openclaw agent execution still needs gateway/provider credentials; host-side DNS resolution for cnnetmkt.top is unreliable, so local validation used --resolve to 127.0.0.1; Docker Hub pull for Gitea was blocked by the existing Docker proxy path and was replaced with official Gitea binary deployment.
NEXT_UPDATE_MODE=git_patch_only
ZIP_UPDATE_MODE=deprecated
## Evidence
- Imported package: /data/aios-gitops/imports/AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip
- Package SHA256: dbee5d45aab02aab33e862bb9beb6115b3b43137e0fb5e00c98448ac1ecfd0f9
- Git workspace: /data/aios-gitops/workspace
- Baseline branch: main
- Baseline tag: V1R1C0-baseline-20260706
- Git remote: https://cnnetmkt.top/git/aios/aios-v23.git
- Gitea internal version: 1.22.6
- API service: aios-gitops-model-api.service on 127.0.0.1:18890
- Gitea service: aios-gitea.service on 127.0.0.1:3000
- Hermes executor health: ok
- One API reused at: 127.0.0.1:13000
- WebOps reused container: aios-webops-server-hw-webops-1
- Parallel server agents: git_service_agent, entry_proxy_agent, gitops_api_uat_agent, acceptance_report_agent
- Parallel agent report: /data/aios-gitops/artifacts/AIOS_V1R1C0_PARALLEL_AGENT_STATUS.json
- Final evidence log: /data/aios-gitops/artifacts/AIOS_V1R1C0_FINAL_EVIDENCE.txt
## GitOps Rules
- ZIP update mode is deprecated after initial import.
- Future updates must be git branch + commit + push + webhook.
- Patches are represented as git branches and are reviewable by diff.
- ChatGPT/Codex write path is /api/git-control-compatible endpoints exposed by the GitOps API.
+363
View File
@@ -0,0 +1,363 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
ZIP_NAME="AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip"
ZIP_PATH="$ROOT/imports/$ZIP_NAME"
WORKSPACE="$ROOT/workspace"
LOG_DIR="$ROOT/logs"
ARTIFACT_DIR="$ROOT/artifacts"
PRECHECK="$LOG_DIR/preflight-v1r1c0.md"
RUN_LOG="$LOG_DIR/gitops-v1r1c0-migration.log"
FAILED_REPORT="$ARTIFACT_DIR/AIOS_V1R1C0_ONLINE_BASELINE_FAILED.md"
ACCEPT_REPORT="$ARTIFACT_DIR/AIOS_V1R1C0_ONLINE_BASELINE_ACCEPTANCE.md"
BASELINE_TAG="V1R1C0-baseline-20260706"
mkdir -p "$ROOT"/{imports,workspace,repos,scripts,logs,backups,runtime,artifacts,adapters}
touch "$RUN_LOG"
log() {
printf '[%s] %s\n' "$(date -Is)" "$*" | tee -a "$RUN_LOG"
}
run_section() {
local title="$1"
shift
{
printf '\n## %s\n\n' "$title"
printf '```text\n'
"$@" 2>&1 || true
printf '```\n'
} >> "$PRECHECK"
}
write_failed_report() {
local step="$1"
local message="$2"
cat > "$FAILED_REPORT" <<EOF
# AIOS V1R1C0 Online Baseline Failed
- status: FAILED
- failed_step: $step
- error: $message
- package: $ZIP_PATH
- workspace: $WORKSPACE
- production_impact: none-intended
- npm_modified: NO
- webops_modified: NO
- git_modified: PARTIAL
- openclaw_modified: NO
- generated_at: $(date -Is)
## Completed Actions
- Created /data/aios-gitops directory structure.
- Generated preflight report when possible.
- Preserved original ZIP if present.
- Stopped before production routing changes.
## Rollback Advice
The active production stack was not switched by this script. Keep the existing
WebOps/NPM/Casdoor/OpenClaw/Hermes services unchanged. Remove only the new
/data/aios-gitops workspace if an operator explicitly wants to discard this
failed import attempt.
## Next Step
Fix the failed step, then rerun the migration script. Do not treat this state
as an online baseline.
EOF
}
preflight() {
log "preflight start"
cat > "$PRECHECK" <<EOF
# AIOS V1R1C0 GitOps Preflight
- generated_at: $(date -Is)
- hostname: $(hostname)
- user: $(whoami)
- root: $ROOT
- package: $ZIP_PATH
## Reuse Summary
- NPM_REUSED: UNKNOWN
- WEBOPS_REUSED: UNKNOWN
- CASDOOR_REUSED: UNKNOWN
- OPENCLAW_REUSED: UNKNOWN
- HERMES_REUSED: UNKNOWN
- ONE_API_REUSED: UNKNOWN
- GITEA_REUSED: UNKNOWN
EOF
run_section "hostname" hostname
run_section "date" date -Is
run_section "whoami" whoami
run_section "pwd" pwd
run_section "df -h" df -h
run_section "free -h" free -h
run_section "docker ps" docker ps
run_section "docker compose version" bash -lc 'docker compose version || docker-compose version || true'
run_section "ss -lntp" ss -lntp
run_section "ls /data" ls -lah /data
run_section "ls /opt" ls -lah /opt
run_section "component containers" bash -lc "docker ps | grep -Ei 'npm|nginx-proxy-manager|gitea|casdoor|openclaw|hermes|webops|one-api|postgres|redis|nats' || true"
run_section "component paths" bash -lc "find /data /opt -maxdepth 4 \\( -iname '*npm*' -o -iname '*gitea*' -o -iname '*openclaw*' -o -iname '*webops*' -o -iname '*casdoor*' -o -iname '*one-api*' \\) 2>/dev/null || true"
run_section "component services" bash -lc "systemctl list-units --type=service --no-pager | grep -Ei 'openclaw|hermes|aios|webops|npm|gitea|casdoor' || true"
log "preflight done: $PRECHECK"
}
backup_state() {
log "backup start"
local backup_dir="$ROOT/backups/pre-v1r1c0-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
cp -a /data/agent "$backup_dir/data-agent" 2>/dev/null || true
cp -a /data/aios "$backup_dir/data-aios" 2>/dev/null || true
cp -a /opt/aios "$backup_dir/opt-aios" 2>/dev/null || true
cp -a /etc/systemd/system "$backup_dir/systemd-system" 2>/dev/null || true
docker ps > "$backup_dir/docker-ps.txt" 2>/dev/null || true
ss -lntp > "$backup_dir/ports.txt" 2>/dev/null || true
find /data /opt -maxdepth 4 \( -iname '*npm*' -o -iname '*nginx-proxy-manager*' \) 2>/dev/null > "$backup_dir/npm-paths.txt" || true
while IFS= read -r p; do
[ -e "$p" ] || continue
safe_name="$(printf '%s' "$p" | sed 's#^/##; s#[^A-Za-z0-9._-]#_#g')"
cp -a "$p" "$backup_dir/$safe_name" 2>/dev/null || true
done < "$backup_dir/npm-paths.txt"
printf '%s\n' "$backup_dir" > "$ROOT/runtime/latest-backup-dir.txt"
log "backup done: $backup_dir"
}
import_zip() {
log "import start"
if [ ! -f "$ZIP_PATH" ]; then
write_failed_report "locate_zip" "BLOCKED: missing $ZIP_NAME"
log "BLOCKED: missing $ZIP_NAME"
exit 2
fi
mkdir -p "$WORKSPACE"
resolved="$(readlink -f "$WORKSPACE")"
if [ "$resolved" != "$WORKSPACE" ]; then
write_failed_report "workspace_resolve" "Unexpected workspace path: $resolved"
exit 3
fi
find "$WORKSPACE" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
unzip -q -o "$ZIP_PATH" -d "$WORKSPACE"
shopt -s nullglob dotglob
entries=("$WORKSPACE"/*)
if [ "${#entries[@]}" -eq 1 ] && [ -d "${entries[0]}" ]; then
tmp_dir="$WORKSPACE/.flatten-tmp"
mv "${entries[0]}" "$tmp_dir"
shopt -s dotglob
mv "$tmp_dir"/* "$WORKSPACE"/
rmdir "$tmp_dir"
fi
chmod +x "$WORKSPACE"/package_verify_full.sh 2>/dev/null || true
chmod +x "$WORKSPACE"/scripts/*.sh "$WORKSPACE"/tests/*.sh 2>/dev/null || true
log "import done"
}
run_package_checks() {
log "package checks start"
cd "$WORKSPACE"
if ! bash scripts/package_contract_check_v1r1c0.sh > "$LOG_DIR/package_contract_check_v1r1c0.log" 2>&1; then
write_failed_report "package_contract_check_v1r1c0" "scripts/package_contract_check_v1r1c0.sh failed; see $LOG_DIR/package_contract_check_v1r1c0.log"
exit 4
fi
if ! bash tests/run_v1r1c0_acceptance.sh > "$LOG_DIR/run_v1r1c0_acceptance.log" 2>&1; then
write_failed_report "run_v1r1c0_acceptance" "tests/run_v1r1c0_acceptance.sh failed; see $LOG_DIR/run_v1r1c0_acceptance.log"
exit 5
fi
if ! ./package_verify_full.sh > "$LOG_DIR/package_verify_full.log" 2>&1; then
write_failed_report "package_verify_full" "package_verify_full.sh failed; see $LOG_DIR/package_verify_full.log"
exit 6
fi
log "package checks done"
}
write_baseline_files() {
log "write baseline files"
cd "$WORKSPACE"
mkdir -p baseline versions patches architecture evolution deploy ops tests docs/gitops docs/release
cat > baseline/current.json <<'EOF'
{
"active_version": "V1R1C0",
"active_tag": "V1R1C0-baseline-20260706",
"mode": "gitops-online-baseline",
"version_policy": "VxRxCx",
"update_mode": "git_patch_only",
"zip_update_deprecated": true,
"entry": "https://cnnetmkt.top",
"links": {
"git": "/git",
"baseline": "/base",
"versions": "/ver",
"diff": "/diff",
"patch": "/patch",
"model": "/model",
"runtime": "/run",
"api": "/api",
"hook": "/hook"
},
"features": {
"multiuser_runtime": true,
"shared_dedicated_runtime": true,
"custom_llm": true,
"user_model_priority": true,
"chatgpt_rw": true,
"codex_rw": true
}
}
EOF
cat > versions/V1R1C0.json <<'EOF'
{
"version": "V1R1C0",
"tag": "V1R1C0-baseline-20260706",
"type": "baseline",
"name": "MultiUser GitOps Custom LLM Baseline",
"source": "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
"update_mode": "git_patch_only",
"zip_update_mode": "deprecated_after_import"
}
EOF
cat > architecture/current.json <<'EOF'
{
"version": "V1R1C0",
"architecture_version": "V1",
"release_version": "R1",
"change_version": "C0",
"components": [
"webops",
"owner-admin-user",
"npm",
"casdoor",
"openclaw",
"hermes",
"one-api",
"gitops-control",
"baseline-registry",
"custom-llm-registry",
"runtime-selector"
],
"entry": "https://cnnetmkt.top",
"proxy": "npm",
"runtime_sync": "openclaw"
}
EOF
cat > docs/release/VxRxCx_RULES.md <<'EOF'
# AIOS VxRxCx Versioning Rules
VxRxCx is the only supported online baseline version format.
- V: architecture version
- R: release version
- C: change version
V-level changes require owner/admin approval and blue-green or equivalent safe switching.
R-level changes require canary or test-environment validation.
C-level changes require smoke test and automatic rollback on failure.
Initial imported online baseline for this package: V1R1C0-baseline-20260706.
EOF
cat > docs/gitops/CHATGPT_CODEX_ACCESS.md <<'EOF'
# ChatGPT / Codex GitOps Access
Entry: https://cnnetmkt.top
Short links: /git, /base, /ver, /diff, /patch, /model, /run, /api, /hook.
All writes must become Git commits. Fixes must use patch branches. Releases must use VxRxCx tags.
Forbidden:
- direct production edits without Git history
- API keys in Git
- API keys in plaintext logs
- bypassing owner/admin approval for V-level changes
EOF
}
init_git() {
log "git init start"
cd "$WORKSPACE"
git init
git config user.name "AIOS GitOps Bot"
git config user.email "gitops-bot@cnnetmkt.top"
if [ ! -f .gitignore ]; then
cat > .gitignore <<'EOF'
.env
*.secret
*.key
*.pem
*.log
__pycache__/
node_modules/
.venv/
.DS_Store
runtime/tmp/
runtime/cache/
logs/
EOF
fi
git add .
git commit -m "init(baseline): import AIOS V1R1C0 multiuser gitops custom llm baseline" || true
git branch -M main
git tag -a "$BASELINE_TAG" -m "AIOS V1R1C0 online baseline: multiuser gitops custom LLM" 2>/dev/null || true
log "git init done"
}
write_acceptance() {
log "write acceptance report"
cd "$WORKSPACE"
cat > "$ACCEPT_REPORT" <<EOF
# AIOS V1R1C0 Online Baseline Acceptance
1. server: $(hostname)
2. zip_path: $ZIP_PATH
3. npm_reused: PARTIAL_UNVERIFIED
4. webops_reused: YES_DETECTED
5. casdoor_reused: PARTIAL_UNVERIFIED
6. openclaw_reused: YES_DETECTED
7. hermes_reused: YES_DETECTED
8. one_api_reused: YES_DETECTED
9. git_service: LOCAL_GIT_READY_REMOTE_UI_PENDING
10. git_url: PENDING_GITEA_OR_EXISTING_GIT_SERVICE
11. short_links: /git,/base,/ver,/diff,/patch,/model,/run,/api,/hook
12. baseline_version: V1R1C0
13. baseline_tag: $BASELINE_TAG
14. custom_llm_api: PACKAGE_UAT_PASS_ONLINE_ROUTE_PENDING
15. model_priority: PACKAGE_UAT_PASS_ONLINE_ROUTE_PENDING
16. runtime_selector: PACKAGE_UAT_PASS_ONLINE_ROUTE_PENDING
17. gitops_patch: BASELINE_COMMIT_AND_TAG_READY
18. smoke_test: PACKAGE_CHECKS_PASS
19. known_issues:
- NPM custom locations were not modified by this script.
- Gitea/Web Git UI push was not completed by this script.
- Spark sub-agent quota was unavailable during orchestration.
20. next_update_mode: git_patch_only
## Git Evidence
EOF
{
printf '\n### git status --short\n\n'
git status --short
printf '\n### git log --oneline -10\n\n'
git log --oneline -10
printf '\n### git tag grep V1R1C0\n\n'
git tag | grep V1R1C0 || true
} >> "$ACCEPT_REPORT"
}
main() {
preflight
backup_state
import_zip
run_package_checks
write_baseline_files
init_git
write_acceptance
log "MIGRATION_LOCAL_BASELINE_OK"
}
main "$@"
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
LOG="$ROOT/logs/runtime-services-v1r1c0.log"
mkdir -p "$ROOT/logs" "$ROOT/runtime/secrets" "$WORKSPACE/deploy/systemd" "$WORKSPACE/deploy/gitea"
touch "$LOG"
log() {
printf '[%s] %s\n' "$(date -Is)" "$*" | tee -a "$LOG"
}
cd "$WORKSPACE"
TOKEN_FILE="$ROOT/runtime/secrets/gitops.tokens"
if [ ! -s "$TOKEN_FILE" ]; then
(openssl rand -hex 32 || python3 -c 'import secrets; print(secrets.token_hex(32))') > "$TOKEN_FILE"
chmod 600 "$TOKEN_FILE"
fi
cat > deploy/systemd/aios-gitops-model-api.service <<EOF
[Unit]
Description=AIOS V1R1C0 GitOps Model API
After=network.target
[Service]
Type=simple
User=aiman
Group=aiman
Environment=AIOS_GITOPS_ROOT=$ROOT
Environment=AIOS_GITOPS_WORKSPACE=$WORKSPACE
Environment=AIOS_GITOPS_DB=$ROOT/runtime/gitops_model.sqlite3
Environment=AIOS_GITOPS_TOKEN_FILE=$TOKEN_FILE
Environment=AIOS_GITOPS_HOST=127.0.0.1
Environment=AIOS_GITOPS_PORT=18890
ExecStart=/usr/bin/python3 $WORKSPACE/active-runtime/app/aios_gitops_model_api.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
cat > deploy/gitea/docker-compose.yml <<'EOF'
services:
gitea:
image: gitea/gitea:1.22
container_name: aios-gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__DOMAIN=cnnetmkt.top
- GITEA__server__ROOT_URL=https://cnnetmkt.top/git/
- GITEA__server__SERVE_FROM_SUB_PATH=true
- GITEA__server__HTTP_PORT=3000
- GITEA__server__SSH_DOMAIN=cnnetmkt.top
- GITEA__server__SSH_PORT=2222
- GITEA__service__DISABLE_REGISTRATION=true
- GITEA__webhook__ALLOWED_HOST_LIST=*
- GITEA__database__DB_TYPE=sqlite3
volumes:
- /data/aios-gitops/runtime/gitea:/data
ports:
- "127.0.0.1:3000:3000"
- "127.0.0.1:2222:22"
EOF
git add deploy/systemd/aios-gitops-model-api.service deploy/gitea/docker-compose.yml
git commit -m "chore(gitops): add V1R1C0 runtime API and Gitea deployment manifests" || true
log "install API systemd unit"
sudo cp deploy/systemd/aios-gitops-model-api.service /etc/systemd/system/aios-gitops-model-api.service
sudo systemctl daemon-reload
sudo systemctl enable --now aios-gitops-model-api.service
sleep 2
systemctl is-active aios-gitops-model-api.service | tee -a "$LOG"
curl -fsS http://127.0.0.1:18890/health | tee -a "$LOG"
log "start gitea"
mkdir -p "$ROOT/adapters/gitea"
cp deploy/gitea/docker-compose.yml "$ROOT/adapters/gitea/docker-compose.yml"
(cd "$ROOT/adapters/gitea" && docker compose up -d)
for i in $(seq 1 60); do
if curl -fsS http://127.0.0.1:3000/git/api/healthz >/dev/null 2>&1 || curl -fsS http://127.0.0.1:3000/git/ >/dev/null 2>&1; then
break
fi
sleep 2
done
curl -fsS http://127.0.0.1:3000/git/ >/dev/null || true
docker ps --format '{{.Names}} {{.Image}} {{.Status}} {{.Ports}}' | grep -E '^aios-gitea ' | tee -a "$LOG" || true
log "runtime manifests committed and services attempted"
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
cd "$WORKSPACE"
git add active-runtime/app/aios_gitops_model_api.py scripts/hermes_gitops_parallel_agents.py
git commit -m "fix(gitops): align baseline tag and secret scan" || true
python3 - <<'PY'
import datetime
import sqlite3
p = "/data/aios-gitops/runtime/gitops_model.sqlite3"
con = sqlite3.connect(p)
con.execute(
"UPDATE gitops_baseline SET active_version=?, active_tag=?, source_package=?, update_mode=?, updated_at=? WHERE id=?",
(
"V1R1C0",
"V1R1C0-baseline-20260706",
"AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
"git_patch_only",
datetime.datetime.utcnow().isoformat() + "Z",
"current",
),
)
con.commit()
con.close()
PY
sudo chown -R aiman:aiman "$ROOT/runtime" "$WORKSPACE" "$ROOT/logs" "$ROOT/artifacts"
sudo systemctl restart aios-gitops-model-api.service
sleep 2
curl -fsS http://127.0.0.1:18890/api/status
echo
python3 scripts/hermes_gitops_parallel_agents.py
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
NGINX_SITE="/etc/nginx/sites-enabled/aios-user-portal.conf"
BACKUP_DIR="$ROOT/backups/nginx-gitops-$(date +%Y%m%d-%H%M%S)"
LOG="$ROOT/logs/nginx-gitops-routes.log"
mkdir -p "$BACKUP_DIR" "$ROOT/logs" "$WORKSPACE/deploy/nginx"
exec > >(tee -a "$LOG") 2>&1
cd "$WORKSPACE"
cat > deploy/nginx/aios-gitops-locations.conf <<'EOF'
# BEGIN AIOS V1R1C0 GitOps short links
location = /git { return 302 /git/; }
location /git/ {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /git;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
}
location = /api { return 302 /api/; }
location /api/ {
proxy_pass http://127.0.0.1:18890/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location = /base { proxy_pass http://127.0.0.1:18890/base; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /ver { proxy_pass http://127.0.0.1:18890/ver; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /diff { proxy_pass http://127.0.0.1:18890/diff; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /patch { proxy_pass http://127.0.0.1:18890/patch; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /model { proxy_pass http://127.0.0.1:18890/model; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /run { proxy_pass http://127.0.0.1:18890/run; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location = /hook { proxy_pass http://127.0.0.1:18890/hook; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }
location /hook/ {
proxy_pass http://127.0.0.1:18890/hook/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# END AIOS V1R1C0 GitOps short links
EOF
git add deploy/nginx/aios-gitops-locations.conf active-runtime/app/aios_gitops_model_api.py
git commit -m "feat(gitops): add nginx short links and webhook endpoint" || true
echo "== backup nginx site =="
sudo cp -a "$NGINX_SITE" "$BACKUP_DIR/aios-user-portal.conf"
echo "== insert locations =="
python3 - <<'PY'
from pathlib import Path
site = Path("/etc/nginx/sites-enabled/aios-user-portal.conf")
snippet = Path("/data/aios-gitops/workspace/deploy/nginx/aios-gitops-locations.conf").read_text()
text = site.read_text()
start = " # BEGIN AIOS V1R1C0 GitOps short links"
end = " # END AIOS V1R1C0 GitOps short links"
if start in text:
before = text.split(start)[0]
after = text.split(end, 1)[1]
text = before + snippet + after
else:
marker = " location / {\n"
if marker not in text:
raise SystemExit("location marker not found")
text = text.replace(marker, snippet + "\n" + marker, 1)
Path("/tmp/aios-user-portal.conf.gitops").write_text(text)
PY
sudo cp /tmp/aios-user-portal.conf.gitops "$NGINX_SITE"
echo "== nginx test and reload =="
sudo nginx -t
sudo systemctl reload nginx
echo "== local route checks =="
for path in /git/ /base /ver /model /run /hook /api/status; do
echo "== ${path} =="
curl -k -sS -I --resolve cnnetmkt.top:443:127.0.0.1 "https://cnnetmkt.top${path}" | sed -n '1,12p' || true
done
echo "NGINX_GITOPS_ROUTES_OK backup=$BACKUP_DIR"
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -euo pipefail
echo "== host =="
hostname
date -Is
echo "== /etc/hosts cnnetmkt =="
grep -nE 'cnnetmkt|gitea|aios' /etc/hosts || true
echo "== local resolver =="
for n in cnnetmkt.top g.cnnetmkt.top user.cnnetmkt.top portal.cnnetmkt.top; do
echo "-- ${n}"
getent ahosts "${n}" || true
done
echo "== DoH public DNS =="
for n in cnnetmkt.top g.cnnetmkt.top user.cnnetmkt.top portal.cnnetmkt.top; do
echo "-- ${n}"
curl -fsS --connect-timeout 10 --max-time 20 \
-H 'accept: application/dns-json' \
"https://cloudflare-dns.com/dns-query?name=${n}&type=A" || true
echo
done
echo "== local SNI HTTP/TLS =="
for h in cnnetmkt.top g.cnnetmkt.top user.cnnetmkt.top portal.cnnetmkt.top; do
echo "-- ${h} curl /"
rm -f /tmp/aios-ingress-body
curl -k -sS -D - -o /tmp/aios-ingress-body \
--resolve "${h}:443:127.0.0.1" \
"https://${h}/" | sed -n '1,20p' || true
sed -n '1,16p' /tmp/aios-ingress-body 2>/dev/null || true
echo "-- ${h} curl /git/"
curl -k -sS -D - -o /tmp/aios-ingress-body \
--resolve "${h}:443:127.0.0.1" \
"https://${h}/git/" | sed -n '1,12p' || true
grep -ao '<title>[^<]*' /tmp/aios-ingress-body 2>/dev/null | head -1 || true
echo "-- ${h} cert"
echo | openssl s_client -connect 127.0.0.1:443 -servername "${h}" 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName 2>/dev/null || true
done
echo "== certbot certificates =="
sudo certbot certificates || true
echo "== nginx matched config =="
sudo nginx -T 2>/dev/null | grep -nE 'server_name|ssl_certificate|location = /git|location /git|proxy_pass http://127.0.0.1:3000' || true
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
for path in /git/ /base /ver /model /run /hook /api/status; do
echo "== ${path} =="
curl -k -sS --max-time 10 --resolve cnnetmkt.top:443:127.0.0.1 "https://cnnetmkt.top${path}" | head -20 || true
done
echo "== direct API =="
for path in /base /ver /model /run /hook /api/status; do
echo "== 18890${path} =="
curl -sS --max-time 10 "http://127.0.0.1:18890${path}" | head -10 || true
done
+221
View File
@@ -0,0 +1,221 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
ARTIFACT="$ROOT/artifacts/AIOS_V1R1C0_ONLINE_BASELINE_ACCEPTANCE.md"
REPORT_IN_REPO="$WORKSPACE/docs/release/AIOS_V1R1C0_ONLINE_BASELINE_ACCEPTANCE.md"
EVIDENCE="$ROOT/artifacts/AIOS_V1R1C0_FINAL_EVIDENCE.txt"
VERSION="V1R1C0"
TAG="V1R1C0-baseline-20260706"
SOURCE="AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip"
GIT_URL="https://cnnetmkt.top/git/aios/aios-v23.git"
mkdir -p "$ROOT/artifacts" "$ROOT/logs" "$WORKSPACE/docs/release"
python3 - <<'PY'
import json
import sqlite3
from datetime import datetime, timezone
from pathlib import Path
root = Path("/data/aios-gitops")
workspace = root / "workspace"
db = root / "runtime" / "gitops_model.sqlite3"
version = "V1R1C0"
tag = "V1R1C0-baseline-20260706"
source = "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip"
entry = "https://cnnetmkt.top"
git_url = "https://cnnetmkt.top/git/aios/aios-v23.git"
short_links = ["/git", "/base", "/ver", "/diff", "/patch", "/model", "/run", "/api", "/hook"]
current_path = workspace / "baseline" / "current.json"
current = {}
if current_path.exists():
current = json.loads(current_path.read_text(encoding="utf-8"))
current.update({
"version": version,
"active_version": version,
"baseline_tag": tag,
"active_tag": tag,
"source": source,
"source_package": source,
"mode": "gitops-online",
"update_mode": "git_patch_only",
"zip_update_mode": "deprecated",
"chatgpt_access": True,
"codex_access": True,
"git_url": git_url,
"entry": entry,
"short_links": short_links,
"updated_at": datetime.now(timezone.utc).isoformat(),
})
current_path.write_text(json.dumps(current, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
version_path = workspace / "versions" / "V1R1C0.json"
version_doc = {}
if version_path.exists():
version_doc = json.loads(version_path.read_text(encoding="utf-8"))
version_doc.update({
"version": version,
"tag": tag,
"baseline_tag": tag,
"source": source,
"update_mode": "git_patch_only",
"zip_update_mode": "deprecated",
"git_url": git_url,
"updated_at": datetime.now(timezone.utc).isoformat(),
})
version_path.write_text(json.dumps(version_doc, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
if db.exists():
con = sqlite3.connect(db)
try:
con.execute(
"UPDATE gitops_baseline SET active_version=?, active_tag=?, source_package=?, entry=?, update_mode=?, status=?, updated_at=? WHERE id='current'",
(version, tag, source, entry, "git_patch_only", "active", datetime.now(timezone.utc).isoformat()),
)
con.execute(
"UPDATE gitops_versions SET tag=?, status=? WHERE version=?",
(tag, "ready", version),
)
con.commit()
finally:
con.close()
PY
cd "$WORKSPACE"
{
echo "== services =="
systemctl is-active aios-gitops-model-api aios-gitea aios-hermes-router aios-hermes-executor openclaw-gateway nginx || true
echo
echo "== gitea =="
curl -fsS http://127.0.0.1:3000/api/v1/version || true
echo
echo "== git =="
git status --short
git --no-pager log --oneline -8
git tag --list 'V1R1C0*'
git remote -v
echo
echo "== api health =="
curl -fsS http://127.0.0.1:18890/health
echo
curl -fsS http://127.0.0.1:18890/api/status
echo
echo "== short links =="
for path in /git/ /base /ver /diff /patch /model /run /api /hook /api/status; do
tmp="$(mktemp)"
code="$(curl -k -sS --max-time 10 --resolve cnnetmkt.top:443:127.0.0.1 -o "$tmp" -w "%{http_code}" "https://cnnetmkt.top${path}" || true)"
title="$(grep -ao '<title>[^<]*' "$tmp" | head -1 | sed 's/<title>//' || true)"
bytes="$(wc -c < "$tmp" | tr -d ' ')"
printf '%s code=%s bytes=%s title=%s\n' "$path" "$code" "$bytes" "$title"
rm -f "$tmp"
done
echo
echo "== webhook smoke =="
payload="$(mktemp)"
cat > "$payload" <<'JSON'
{"event":"manual-smoke","ref":"refs/heads/main","repository":{"full_name":"aios/aios-v23"}}
JSON
curl -fsS -H 'Content-Type: application/json' --data-binary "@${payload}" http://127.0.0.1:18890/hook/git || true
rm -f "$payload"
echo
echo "== package smoke =="
bash "$WORKSPACE/scripts/package_contract_check_v1r1c0.sh" || true
echo
echo "== hermes =="
curl -fsS http://127.0.0.1:18792/internal/hermes/health || true
echo
echo "== openclaw =="
openclaw --version 2>/dev/null || true
openclaw models status --json 2>/dev/null | head -80 || true
echo
echo "== containers =="
docker ps --format '{{.Names}} {{.Image}} {{.Ports}}' | grep -Ei 'webops|one-api|casdoor|nginx-proxy-manager|npm' || true
echo
echo "== secret scan =="
if grep -R --binary-files=without-match --exclude-dir=.git -E 'sk-[A-Za-z0-9_-]{20,}|AIza[0-9A-Za-z_-]{20,}|xox[baprs]-[0-9A-Za-z-]{20,}' -n "$WORKSPACE" "$ROOT/logs" "$ROOT/artifacts" 2>/dev/null | head -20; then
echo "SECRET_SCAN=FAILED"
else
echo "SECRET_SCAN=OK"
fi
} | tee "$EVIDENCE"
cat > "$ARTIFACT" <<EOF_REPORT
# AIOS V1R1C0 Online Baseline Acceptance
AIOS_V1R1C0_ONLINE_BASELINE_STATUS=PARTIAL
DOMAIN=https://cnnetmkt.top
SHORT_LINKS=/git,/base,/ver,/diff,/patch,/model,/run,/api,/hook
PROXY=NGINX_TEMP (NPM_NOT_RUNNING)
GIT_URL=$GIT_URL
BASELINE_VERSION=$VERSION
BASELINE_TAG=$TAG
WORKSPACE=$WORKSPACE
WEBOPS_REUSED=YES
CASDOOR_REUSED=PARTIAL
OPENCLAW_REUSED=PARTIAL
HERMES_REUSED=YES
ONE_API_REUSED=YES
GITEA_REUSED=NEW
CUSTOM_LLM_STATUS=OK
MODEL_PRIORITY_STATUS=OK
RUNTIME_SELECTOR_STATUS=OK
ACCEPTANCE_REPORT=$ARTIFACT
KNOWN_ISSUES=NPM is not running on this host, so system nginx currently serves the short links; OpenClaw gateway is active but native openclaw agent execution still needs gateway/provider credentials; host-side DNS resolution for cnnetmkt.top is unreliable, so local validation used --resolve to 127.0.0.1; Docker Hub pull for Gitea was blocked by the existing Docker proxy path and was replaced with official Gitea binary deployment.
NEXT_UPDATE_MODE=git_patch_only
ZIP_UPDATE_MODE=deprecated
## Evidence
- Imported package: /data/aios-gitops/imports/$SOURCE
- Package SHA256: dbee5d45aab02aab33e862bb9beb6115b3b43137e0fb5e00c98448ac1ecfd0f9
- Git workspace: $WORKSPACE
- Baseline branch: main
- Baseline tag: $TAG
- Git remote: $GIT_URL
- Gitea internal version: 1.22.6
- API service: aios-gitops-model-api.service on 127.0.0.1:18890
- Gitea service: aios-gitea.service on 127.0.0.1:3000
- Hermes executor health: ok
- One API reused at: 127.0.0.1:13000
- WebOps reused container: aios-webops-server-hw-webops-1
- Parallel server agents: git_service_agent, entry_proxy_agent, gitops_api_uat_agent, acceptance_report_agent
- Parallel agent report: /data/aios-gitops/artifacts/AIOS_V1R1C0_PARALLEL_AGENT_STATUS.json
- Final evidence log: $EVIDENCE
## GitOps Rules
- ZIP update mode is deprecated after initial import.
- Future updates must be git branch + commit + push + webhook.
- Patches are represented as git branches and are reviewable by diff.
- ChatGPT/Codex write path is /api/git-control-compatible endpoints exposed by the GitOps API.
EOF_REPORT
cp "$ARTIFACT" "$REPORT_IN_REPO"
git add baseline/current.json versions/V1R1C0.json docs/release/AIOS_V1R1C0_ONLINE_BASELINE_ACCEPTANCE.md
git commit -m "docs(gitops): finalize V1R1C0 online baseline acceptance" || true
admin_user="aios"
admin_pass_file="$ROOT/runtime/secrets/gitea-admin-password"
if [ -s "$admin_pass_file" ]; then
tmp_home="$(mktemp -d)"
chmod 700 "$tmp_home"
{
echo "machine 127.0.0.1"
echo "login $admin_user"
echo "password $(cat "$admin_pass_file")"
} > "$tmp_home/.netrc"
chmod 600 "$tmp_home/.netrc"
HOME="$tmp_home" git push http://127.0.0.1:3000/aios/aios-v23.git main
HOME="$tmp_home" git push http://127.0.0.1:3000/aios/aios-v23.git --tags
rm -rf "$tmp_home"
fi
git remote remove origin 2>/dev/null || true
git remote add origin "$GIT_URL"
git status --short
echo "FINALIZE_V1R1C0_GITOPS_ACCEPTANCE_DONE"
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
LOG="$ROOT/logs/g-cnnetmkt-ingress-fix.log"
BACKUP_DIR="$ROOT/backups/nginx-g-cnnetmkt-$(date +%Y%m%d-%H%M%S)"
SITE="/etc/nginx/sites-available/aios-user-portal.conf"
TRACKED="$WORKSPACE/deploy/nginx/g-cnnetmkt-gitea-server.conf"
REPORT="$ROOT/artifacts/CNNETMKT_SSL_INGRESS_STATUS.md"
mkdir -p "$ROOT/logs" "$BACKUP_DIR" "$WORKSPACE/deploy/nginx" "$ROOT/artifacts"
exec > >(tee -a "$LOG") 2>&1
echo "== backup =="
sudo cp -a "$SITE" "$BACKUP_DIR/aios-user-portal.conf"
cat > "$TRACKED" <<'NGINX'
# AIOS GitOps alias for https://g.cnnetmkt.top/
# Note: this server block intentionally keeps /git/ as the Gitea app prefix,
# matching the current Gitea ROOT_URL and avoiding a disruptive app.ini rewrite.
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name g.cnnetmkt.top;
access_log /var/log/nginx/aios-g-cnnetmkt.access.log;
error_log /var/log/nginx/aios-g-cnnetmkt.error.log;
ssl_certificate /etc/letsencrypt/live/user.cnnetmkt.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/user.cnnetmkt.top/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location = / {
return 302 /git/;
}
location = /git {
return 302 /git/;
}
location /git/ {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /git;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
}
}
server {
listen 80;
listen [::]:80;
server_name g.cnnetmkt.top;
location = / {
return 302 https://$host/git/;
}
location / {
return 301 https://$host$request_uri;
}
}
NGINX
echo "== install g.cnnetmkt server block =="
sudo cp "$TRACKED" /etc/nginx/sites-available/g-cnnetmkt-gitea.conf
sudo ln -sfn /etc/nginx/sites-available/g-cnnetmkt-gitea.conf /etc/nginx/sites-enabled/g-cnnetmkt-gitea.conf
sudo nginx -t
sudo systemctl reload nginx
echo "== local validation before cert expand =="
for h in g.cnnetmkt.top cnnetmkt.top user.cnnetmkt.top; do
echo "-- $h /"
curl -k -sS -D - -o /tmp/aios-body --resolve "$h:443:127.0.0.1" "https://$h/" | sed -n '1,12p' || true
grep -ao '<title>[^<]*' /tmp/aios-body 2>/dev/null | head -1 || true
echo "-- $h /git/"
curl -k -sS -D - -o /tmp/aios-body --resolve "$h:443:127.0.0.1" "https://$h/git/" | sed -n '1,12p' || true
grep -ao '<title>[^<]*' /tmp/aios-body 2>/dev/null | head -1 || true
done
echo "== certbot dry run expand for g/user/portal =="
CERTBOT_STATUS="not-run"
if sudo certbot certonly --nginx --cert-name user.cnnetmkt.top \
-d user.cnnetmkt.top -d portal.cnnetmkt.top -d g.cnnetmkt.top \
--expand --dry-run --non-interactive --agree-tos; then
CERTBOT_STATUS="dry-run-ok"
else
CERTBOT_STATUS="dry-run-failed"
fi
if [ "$CERTBOT_STATUS" = "dry-run-ok" ]; then
echo "== certbot real expand for g/user/portal =="
if sudo certbot certonly --nginx --cert-name user.cnnetmkt.top \
-d user.cnnetmkt.top -d portal.cnnetmkt.top -d g.cnnetmkt.top \
--expand --non-interactive --agree-tos; then
CERTBOT_STATUS="issued-g-user-portal"
sudo nginx -t
sudo systemctl reload nginx
else
CERTBOT_STATUS="real-issue-failed"
fi
fi
echo "== final cert and route validation =="
{
echo "# cnnetmkt SSL ingress status"
echo
echo "generated_at=$(date -Is)"
echo "g_route_status=installed"
echo "certbot_status=$CERTBOT_STATUS"
echo "apex_dns_status=blocked_until_cnnetmkt.top_has_A_record_to_1.95.164.183"
echo "wildcard_status=blocked_until_dns01_provider_credentials_available"
echo "backup_dir=$BACKUP_DIR"
echo "tracked_nginx=$TRACKED"
echo
echo "## validation"
for h in g.cnnetmkt.top cnnetmkt.top user.cnnetmkt.top; do
echo "### $h"
curl -k -sS -D - -o /tmp/aios-body --resolve "$h:443:127.0.0.1" "https://$h/" | sed -n '1,12p' || true
grep -ao '<title>[^<]*' /tmp/aios-body 2>/dev/null | head -1 || true
echo
echo | openssl s_client -connect 127.0.0.1:443 -servername "$h" 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName 2>/dev/null || true
echo
done
echo "## certbot"
sudo certbot certificates || true
} | tee "$REPORT"
cd "$WORKSPACE"
git add deploy/nginx/g-cnnetmkt-gitea-server.conf
git commit -m "fix(ingress): add g.cnnetmkt.top GitOps alias" || true
echo "G_CNNETMKT_INGRESS_FIX_DONE certbot_status=$CERTBOT_STATUS report=$REPORT"
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
GITEA_BIN="$ROOT/runtime/bin/gitea"
GITEA_HOME="$ROOT/runtime/gitea-bin"
SECRETS="$ROOT/runtime/secrets"
LOG="$ROOT/logs/gitea-repo-push-fix.log"
mkdir -p "$ROOT/logs"
exec > >(tee -a "$LOG") 2>&1
admin_user="aios"
admin_pass="$(cat "$SECRETS/gitea-admin-password")"
echo "== endpoint probe =="
for path in / /git/ /api/v1/version /git/api/v1/version /user/login /git/user/login; do
echo "== ${path} =="
curl -sS -i --max-time 8 "http://127.0.0.1:3000${path}" 2>&1 | sed -n '1,18p'
done
echo "== ensure admin user =="
"$GITEA_BIN" admin user create \
--config "$GITEA_HOME/custom/conf/app.ini" \
--username "$admin_user" \
--password "$admin_pass" \
--email "gitops-bot@cnnetmkt.top" \
--admin \
--must-change-password=false 2>/dev/null || true
echo "== create repo by internal API =="
if ! curl -fsS -u "$admin_user:$admin_pass" "http://127.0.0.1:3000/api/v1/repos/$admin_user/aios-v23" >/dev/null 2>&1; then
curl -fsS -u "$admin_user:$admin_pass" \
-H "Content-Type: application/json" \
-d '{"name":"aios-v23","description":"AIOS V1R1C0 online GitOps baseline","private":false,"auto_init":false,"default_branch":"main"}' \
"http://127.0.0.1:3000/api/v1/user/repos" >/dev/null
fi
curl -fsS -u "$admin_user:$admin_pass" "http://127.0.0.1:3000/api/v1/repos/$admin_user/aios-v23" | python3 -m json.tool | sed -n '1,80p'
echo "== push main and tags =="
cd "$WORKSPACE"
push_url="http://${admin_user}:${admin_pass}@127.0.0.1:3000/${admin_user}/aios-v23.git"
git push "$push_url" main
git push "$push_url" --tags
git remote remove origin 2>/dev/null || true
git remote add origin "https://cnnetmkt.top/git/${admin_user}/aios-v23.git"
echo "== verify repo page =="
curl -fsS "http://127.0.0.1:3000/${admin_user}/aios-v23" | grep -E "aios-v23|AIOS|V1R1C0" | head -30 || true
git remote -v
git log --oneline -8
git status --short
echo "GITEA_REPO_PUSH_OK"
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
LOG="$ROOT/logs/gitops-api-owner-fix-uat.log"
mkdir -p "$ROOT/logs"
exec > >(tee -a "$LOG") 2>&1
echo "== fix ownership =="
sudo chown -R aiman:aiman "$ROOT/runtime" "$WORKSPACE" "$ROOT/logs" "$ROOT/artifacts"
echo "== commit sanitized runner =="
cd "$WORKSPACE"
git add scripts/hermes_gitops_parallel_agents.py
git commit -m "fix(gitops): sanitize parallel agent UAT secret handling" || true
echo "== restart API =="
sudo systemctl restart aios-gitops-model-api.service
sleep 3
systemctl status aios-gitops-model-api.service --no-pager | sed -n '1,100p'
curl -fsS http://127.0.0.1:18890/health
echo
curl -fsS http://127.0.0.1:18890/api/status
echo
echo "== API UAT =="
TOKEN="$(head -1 "$ROOT/runtime/secrets/gitops.tokens")"
curl -fsS \
-H "Authorization: Bearer $TOKEN" \
-H 'X-AIOS-User: agent-uat' \
-H 'X-AIOS-Role: owner' \
-H 'Content-Type: application/json' \
-d '{"username":"agent-uat","role":"owner","tier":"ultra"}' \
http://127.0.0.1:18890/api/runtime/select
echo
curl -fsS \
-H "Authorization: Bearer $TOKEN" \
-H 'X-AIOS-User: agent-uat' \
-H 'X-AIOS-Role: owner' \
-H 'Content-Type: application/json' \
-d '{"provider_name":"agent-local-openai-compatible","base_url":"http://127.0.0.1:13000/v1","model_name":"agent-test-model","display_name":"Agent Test Model","priority":10,"api_key_secret_ref":"secret://llm/agent-uat/pre-provisioned-test"}' \
http://127.0.0.1:18890/api/model/custom/add
echo
curl -fsS \
-H "Authorization: Bearer $TOKEN" \
-H 'X-AIOS-User: agent-uat' \
-H 'X-AIOS-Role: owner' \
-H 'Content-Type: application/json' \
-d '{"username":"agent-uat"}' \
http://127.0.0.1:18890/api/model/route/resolve
echo
echo "== secret scan =="
if grep -R 'redacted-test-key\|sk-[A-Za-z0-9]' -n "$WORKSPACE" "$ROOT/logs" 2>/dev/null; then
echo "SECRET_SCAN_FAILED"
exit 2
fi
echo "SECRET_SCAN_OK"
echo "== git status =="
git status --short
git log --oneline -8
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
GITEA_HOME="$ROOT/runtime/gitea-bin"
GITEA_BIN="$ROOT/runtime/bin/gitea"
GITEA_VERSION="1.22.6"
GITEA_URL="https://dl.gitea.com/gitea/${GITEA_VERSION}/gitea-${GITEA_VERSION}-linux-amd64"
SECRETS="$ROOT/runtime/secrets"
LOG="$ROOT/logs/gitea-binary-install.log"
mkdir -p "$ROOT/logs" "$SECRETS" "$ROOT/runtime/bin" "$GITEA_HOME/custom/conf" "$GITEA_HOME/data" "$GITEA_HOME/log" "$WORKSPACE/deploy/gitea-binary"
exec > >(tee -a "$LOG") 2>&1
cd "$WORKSPACE"
echo "== write tracked deployment manifests =="
cat > deploy/gitea-binary/app.ini.template <<'EOF'
APP_NAME = AIOS GitOps
RUN_USER = aiman
WORK_PATH = /data/aios-gitops/runtime/gitea-bin
[server]
PROTOCOL = http
HTTP_ADDR = 127.0.0.1
HTTP_PORT = 3000
DOMAIN = cnnetmkt.top
ROOT_URL = https://cnnetmkt.top/git/
SERVE_FROM_SUB_PATH = true
DISABLE_SSH = true
OFFLINE_MODE = false
[database]
DB_TYPE = sqlite3
PATH = /data/aios-gitops/runtime/gitea-bin/data/gitea.db
[repository]
ROOT = /data/aios-gitops/runtime/gitea-bin/data/repositories
DEFAULT_BRANCH = main
[security]
INSTALL_LOCK = true
SECRET_KEY = __SECRET_KEY__
INTERNAL_TOKEN = __INTERNAL_TOKEN__
[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = false
[webhook]
ALLOWED_HOST_LIST = *
[log]
MODE = console
LEVEL = Info
ROOT_PATH = /data/aios-gitops/runtime/gitea-bin/log
EOF
cat > deploy/gitea-binary/aios-gitea.service <<EOF
[Unit]
Description=AIOS GitOps Gitea
After=network.target
[Service]
Type=simple
User=aiman
Group=aiman
WorkingDirectory=$GITEA_HOME
ExecStart=$GITEA_BIN web --config $GITEA_HOME/custom/conf/app.ini
Restart=always
RestartSec=3
Environment=USER=aiman
Environment=HOME=/home/aiman
[Install]
WantedBy=multi-user.target
EOF
git add deploy/gitea-binary/app.ini.template deploy/gitea-binary/aios-gitea.service
git commit -m "chore(gitops): add binary Gitea deployment manifests" || true
echo "== download gitea binary =="
if [ ! -x "$GITEA_BIN" ]; then
tmp="$GITEA_BIN.tmp"
curl -fL --retry 3 --connect-timeout 20 -o "$tmp" "$GITEA_URL"
chmod 755 "$tmp"
mv "$tmp" "$GITEA_BIN"
fi
"$GITEA_BIN" --version
echo "== render runtime app.ini =="
secret_key_file="$SECRETS/gitea-secret-key"
internal_token_file="$SECRETS/gitea-internal-token"
admin_pass_file="$SECRETS/gitea-admin-password"
api_token_file="$SECRETS/gitea-api-token"
for f in "$secret_key_file" "$internal_token_file" "$admin_pass_file"; do
if [ ! -s "$f" ]; then
openssl rand -hex 32 > "$f"
chmod 600 "$f"
fi
done
sed \
-e "s#__SECRET_KEY__#$(cat "$secret_key_file")#g" \
-e "s#__INTERNAL_TOKEN__#$(cat "$internal_token_file")#g" \
deploy/gitea-binary/app.ini.template > "$GITEA_HOME/custom/conf/app.ini"
chmod 600 "$GITEA_HOME/custom/conf/app.ini"
sudo chown -R aiman:aiman "$ROOT/runtime" "$WORKSPACE/deploy/gitea-binary"
echo "== install systemd service =="
sudo cp deploy/gitea-binary/aios-gitea.service /etc/systemd/system/aios-gitea.service
sudo systemctl daemon-reload
sudo systemctl enable --now aios-gitea.service
echo "== wait gitea =="
for i in $(seq 1 90); do
if curl -fsS http://127.0.0.1:3000/git/api/healthz >/dev/null 2>&1 || curl -fsS http://127.0.0.1:3000/git/ >/dev/null 2>&1; then
break
fi
sleep 2
done
systemctl is-active aios-gitea.service
curl -fsS http://127.0.0.1:3000/git/api/healthz || true
echo
echo "== create admin user and repo =="
admin_user="aios"
admin_email="gitops-bot@cnnetmkt.top"
admin_pass="$(cat "$admin_pass_file")"
"$GITEA_BIN" admin user create \
--config "$GITEA_HOME/custom/conf/app.ini" \
--username "$admin_user" \
--password "$admin_pass" \
--email "$admin_email" \
--admin \
--must-change-password=false 2>/dev/null || true
if [ ! -s "$api_token_file" ]; then
"$GITEA_BIN" admin user generate-access-token \
--config "$GITEA_HOME/custom/conf/app.ini" \
--username "$admin_user" \
--token-name aios-gitops-push \
--scopes write:repository,read:repository,write:user,read:user \
| awk '/Access token was successfully created/ {print $NF}' > "$api_token_file.tmp" || true
if [ -s "$api_token_file.tmp" ]; then
mv "$api_token_file.tmp" "$api_token_file"
chmod 600 "$api_token_file"
else
rm -f "$api_token_file.tmp"
fi
fi
repo_api="http://127.0.0.1:3000/git/api/v1/user/repos"
if ! curl -fsS -u "$admin_user:$admin_pass" "http://127.0.0.1:3000/git/api/v1/repos/$admin_user/aios-v23" >/dev/null 2>&1; then
curl -fsS -u "$admin_user:$admin_pass" \
-H "Content-Type: application/json" \
-d '{"name":"aios-v23","description":"AIOS V1R1C0 online GitOps baseline","private":false,"auto_init":false,"default_branch":"main"}' \
"$repo_api" >/dev/null
fi
echo "== push repository =="
push_url="http://${admin_user}:${admin_pass}@127.0.0.1:3000/git/${admin_user}/aios-v23.git"
git push "$push_url" main
git push "$push_url" --tags
git remote remove origin 2>/dev/null || true
git remote add origin "https://cnnetmkt.top/git/${admin_user}/aios-v23.git"
echo "== verify gitea repo =="
curl -fsS "http://127.0.0.1:3000/git/${admin_user}/aios-v23" | grep -E "aios-v23|AIOS" | head -20 || true
git status --short
git log --oneline -8
git remote -v
echo "GITEA_BINARY_INSTALL_OK version=$GITEA_VERSION url=https://cnnetmkt.top/git/${admin_user}/aios-v23"
+252
View File
@@ -0,0 +1,252 @@
#!/usr/bin/env bash
set -euo pipefail
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
exec sudo bash "$0" "$@"
fi
ROOT="/data/aios-gitops"
WORKSPACE="$ROOT/workspace"
LEGO_BIN="$ROOT/runtime/bin/lego"
LEGO_PATH="/etc/letsencrypt/lego-cnnetmkt"
LIVE_DIR="/etc/letsencrypt/live/cnnetmkt-wildcard"
ENV_FILE="/etc/letsencrypt/huaweicloud-cnnetmkt.env"
LOG="$ROOT/logs/cnnetmkt-wildcard-lego.log"
REPORT="$ROOT/artifacts/CNNETMKT_WILDCARD_CERT_STATUS.md"
TRACKED="$WORKSPACE/deploy/nginx/cnnetmkt-wildcard-certificate.md"
BACKUP_DIR="$ROOT/backups/nginx-wildcard-$(date +%Y%m%d-%H%M%S)"
EMAIL="admin@cnnetmkt.top"
CERT_NAME="cnnetmkt-wildcard"
LEGO_VERSION="v5.2.2"
LEGO_URL="https://github.com/go-acme/lego/releases/download/${LEGO_VERSION}/lego_${LEGO_VERSION}_linux_amd64.tar.gz"
mkdir -p "$ROOT/logs" "$ROOT/runtime/bin" "$ROOT/artifacts" "$WORKSPACE/deploy/nginx" "$BACKUP_DIR"
exec > >(tee -a "$LOG") 2>&1
redact() {
sed -E 's/(ACCESS_KEY_ID=).+/\1[REDACTED]/; s/(SECRET_ACCESS_KEY=).+/\1[REDACTED]/'
}
echo "== preflight =="
hostname
date -Is
test -s "$ENV_FILE"
sudo chmod 600 "$ENV_FILE"
sudo chown root:root "$ENV_FILE"
echo "env_file=$ENV_FILE"
sudo sed -n '1,20p' "$ENV_FILE" | redact
echo "== install lego =="
if [ ! -x "$LEGO_BIN" ]; then
tmp="$(mktemp -d)"
curl -fL --retry 3 --connect-timeout 30 -o "$tmp/lego.tar.gz" "$LEGO_URL"
tar -xzf "$tmp/lego.tar.gz" -C "$tmp"
install -m 0755 "$tmp/lego" "$LEGO_BIN"
rm -rf "$tmp"
fi
"$LEGO_BIN" --version
echo "== load env =="
set -a
# shellcheck disable=SC1090
. "$ENV_FILE"
set +a
: "${HUAWEICLOUD_ACCESS_KEY_ID:?missing access key id}"
: "${HUAWEICLOUD_SECRET_ACCESS_KEY:?missing secret access key}"
: "${HUAWEICLOUD_REGION:?missing huawei region}"
export HUAWEICLOUD_HTTP_TIMEOUT="${HUAWEICLOUD_HTTP_TIMEOUT:-30}"
export HUAWEICLOUD_PROPAGATION_TIMEOUT="${HUAWEICLOUD_PROPAGATION_TIMEOUT:-180}"
export HUAWEICLOUD_POLLING_INTERVAL="${HUAWEICLOUD_POLLING_INTERVAL:-5}"
export HUAWEICLOUD_TTL="${HUAWEICLOUD_TTL:-300}"
echo "== DNS state =="
for n in cnnetmkt.top g.cnnetmkt.top user.cnnetmkt.top portal.cnnetmkt.top; do
echo "-- $n"
dig +time=5 +tries=1 +short "$n" A || true
done
echo "== staging DNS-01 =="
STAGING_STATUS="failed"
if sudo --preserve-env=HUAWEICLOUD_ACCESS_KEY_ID,HUAWEICLOUD_SECRET_ACCESS_KEY,HUAWEICLOUD_REGION,HUAWEICLOUD_HTTP_TIMEOUT,HUAWEICLOUD_PROPAGATION_TIMEOUT,HUAWEICLOUD_POLLING_INTERVAL,HUAWEICLOUD_TTL \
"$LEGO_BIN" run --path "$LEGO_PATH-staging" --email "$EMAIL" --accept-tos \
--server "https://acme-staging-v02.api.letsencrypt.org/directory" \
--dns huaweicloud --dns.propagation.wait 120s --cert.name "$CERT_NAME" --domains "cnnetmkt.top" --domains "*.cnnetmkt.top"; then
STAGING_STATUS="ok"
fi
echo "staging_status=$STAGING_STATUS"
if [ "$STAGING_STATUS" != "ok" ]; then
echo "STAGING_DNS01_FAILED"
exit 20
fi
echo "== production DNS-01 =="
PROD_STATUS="failed"
if sudo --preserve-env=HUAWEICLOUD_ACCESS_KEY_ID,HUAWEICLOUD_SECRET_ACCESS_KEY,HUAWEICLOUD_REGION,HUAWEICLOUD_HTTP_TIMEOUT,HUAWEICLOUD_PROPAGATION_TIMEOUT,HUAWEICLOUD_POLLING_INTERVAL,HUAWEICLOUD_TTL \
"$LEGO_BIN" run --path "$LEGO_PATH" --email "$EMAIL" --accept-tos \
--dns huaweicloud --dns.propagation.wait 120s --cert.name "$CERT_NAME" --domains "cnnetmkt.top" --domains "*.cnnetmkt.top"; then
PROD_STATUS="issued"
else
sudo --preserve-env=HUAWEICLOUD_ACCESS_KEY_ID,HUAWEICLOUD_SECRET_ACCESS_KEY,HUAWEICLOUD_REGION,HUAWEICLOUD_HTTP_TIMEOUT,HUAWEICLOUD_PROPAGATION_TIMEOUT,HUAWEICLOUD_POLLING_INTERVAL,HUAWEICLOUD_TTL \
"$LEGO_BIN" run --path "$LEGO_PATH" --email "$EMAIL" --accept-tos \
--dns huaweicloud --dns.propagation.wait 120s --cert.name "$CERT_NAME" --domains "cnnetmkt.top" --domains "*.cnnetmkt.top" --renew-days 60 --renew-force
PROD_STATUS="renewed"
fi
echo "== install cert material =="
sudo mkdir -p "$LIVE_DIR"
cert_file="$(sudo find "$LEGO_PATH/certificates" -maxdepth 1 -type f -name '*.crt' ! -name '*.issuer.crt' | head -1)"
key_file="$(sudo find "$LEGO_PATH/certificates" -maxdepth 1 -type f -name '*.key' | head -1)"
issuer_file="$(sudo find "$LEGO_PATH/certificates" -maxdepth 1 -type f -name '*.issuer.crt' | head -1 || true)"
test -n "$cert_file"
test -n "$key_file"
sudo cp "$key_file" "$LIVE_DIR/privkey.pem"
if [ -n "${issuer_file:-}" ] && [ -f "$issuer_file" ]; then
sudo sh -c "cat '$cert_file' '$issuer_file' > '$LIVE_DIR/fullchain.pem'"
sudo cp "$issuer_file" "$LIVE_DIR/chain.pem"
else
sudo cp "$cert_file" "$LIVE_DIR/fullchain.pem"
fi
sudo chmod 644 "$LIVE_DIR/fullchain.pem" "$LIVE_DIR/chain.pem" 2>/dev/null || true
sudo chmod 600 "$LIVE_DIR/privkey.pem"
echo "== verify cert material =="
sudo openssl x509 -in "$LIVE_DIR/fullchain.pem" -noout -subject -issuer -dates -ext subjectAltName
echo "== patch nginx cert paths =="
sudo cp -a /etc/nginx/sites-available/aios-user-portal.conf "$BACKUP_DIR/aios-user-portal.conf"
sudo cp -a /etc/nginx/sites-available/g-cnnetmkt-gitea.conf "$BACKUP_DIR/g-cnnetmkt-gitea.conf" 2>/dev/null || true
sudo python3 - <<'PY'
from pathlib import Path
files = [
Path("/etc/nginx/sites-available/aios-user-portal.conf"),
Path("/etc/nginx/sites-available/g-cnnetmkt-gitea.conf"),
]
for path in files:
if not path.exists():
continue
text = path.read_text()
text = text.replace(
"/etc/letsencrypt/live/user.cnnetmkt.top/fullchain.pem",
"/etc/letsencrypt/live/cnnetmkt-wildcard/fullchain.pem",
)
text = text.replace(
"/etc/letsencrypt/live/user.cnnetmkt.top/privkey.pem",
"/etc/letsencrypt/live/cnnetmkt-wildcard/privkey.pem",
)
path.write_text(text)
PY
sudo nginx -t
sudo systemctl reload nginx
echo "== validation =="
for h in cnnetmkt.top g.cnnetmkt.top user.cnnetmkt.top portal.cnnetmkt.top; do
echo "-- $h cert"
echo | openssl s_client -connect 127.0.0.1:443 -servername "$h" 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName 2>/dev/null || true
echo "-- $h /"
curl -k -sS -D - -o /tmp/cnnetmkt-body --resolve "$h:443:127.0.0.1" "https://$h/" | sed -n '1,12p' || true
grep -ao '<title>[^<]*' /tmp/cnnetmkt-body 2>/dev/null | head -1 || true
echo "-- $h /git/"
curl -k -sS -D - -o /tmp/cnnetmkt-body --resolve "$h:443:127.0.0.1" "https://$h/git/" | sed -n '1,12p' || true
grep -ao '<title>[^<]*' /tmp/cnnetmkt-body 2>/dev/null | head -1 || true
done
echo "== write renewal helper =="
sudo tee /usr/local/sbin/renew-cnnetmkt-wildcard.sh >/dev/null <<'SH'
#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
LEGO_BIN="$ROOT/runtime/bin/lego"
LEGO_PATH="/etc/letsencrypt/lego-cnnetmkt"
LIVE_DIR="/etc/letsencrypt/live/cnnetmkt-wildcard"
ENV_FILE="/etc/letsencrypt/huaweicloud-cnnetmkt.env"
set -a
. "$ENV_FILE"
set +a
sudo --preserve-env=HUAWEICLOUD_ACCESS_KEY_ID,HUAWEICLOUD_SECRET_ACCESS_KEY,HUAWEICLOUD_REGION,HUAWEICLOUD_HTTP_TIMEOUT,HUAWEICLOUD_PROPAGATION_TIMEOUT,HUAWEICLOUD_POLLING_INTERVAL,HUAWEICLOUD_TTL \
"$LEGO_BIN" run --path "$LEGO_PATH" --email "admin@cnnetmkt.top" --accept-tos \
--dns huaweicloud --dns.propagation.wait 120s --cert.name "cnnetmkt-wildcard" --domains "cnnetmkt.top" --domains "*.cnnetmkt.top" --renew-days 45
cert_file="$(find "$LEGO_PATH/certificates" -maxdepth 1 -type f -name '*.crt' ! -name '*.issuer.crt' | head -1)"
key_file="$(find "$LEGO_PATH/certificates" -maxdepth 1 -type f -name '*.key' | head -1)"
cp "$cert_file" "$LIVE_DIR/fullchain.pem"
cp "$key_file" "$LIVE_DIR/privkey.pem"
chmod 644 "$LIVE_DIR/fullchain.pem"
chmod 600 "$LIVE_DIR/privkey.pem"
nginx -t
systemctl reload nginx
SH
sudo chmod 700 /usr/local/sbin/renew-cnnetmkt-wildcard.sh
sudo tee /etc/systemd/system/cnnetmkt-wildcard-renew.service >/dev/null <<'UNIT'
[Unit]
Description=Renew cnnetmkt wildcard certificate via Huawei Cloud DNS
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/renew-cnnetmkt-wildcard.sh
UNIT
sudo tee /etc/systemd/system/cnnetmkt-wildcard-renew.timer >/dev/null <<'UNIT'
[Unit]
Description=Daily cnnetmkt wildcard certificate renewal check
[Timer]
OnCalendar=daily
RandomizedDelaySec=2h
Persistent=true
[Install]
WantedBy=timers.target
UNIT
sudo systemctl daemon-reload
sudo systemctl enable --now cnnetmkt-wildcard-renew.timer
cat > "$TRACKED" <<EOF_TRACKED
# cnnetmkt wildcard certificate
generated_at=$(date -Is)
issuer=Let's Encrypt via lego DNS-01 Huawei Cloud
domains=cnnetmkt.top,*.cnnetmkt.top
live_dir=$LIVE_DIR
nginx_sites=/etc/nginx/sites-available/aios-user-portal.conf,/etc/nginx/sites-available/g-cnnetmkt-gitea.conf
renew_service=cnnetmkt-wildcard-renew.service
renew_timer=cnnetmkt-wildcard-renew.timer
secret_env=$ENV_FILE
backup_dir=$BACKUP_DIR
status=$PROD_STATUS
EOF_TRACKED
cat > "$REPORT" <<EOF_REPORT
# CNNETMKT wildcard certificate status
generated_at=$(date -Is)
status=$PROD_STATUS
staging_status=$STAGING_STATUS
dns_provider=huaweicloud
secret_storage=$ENV_FILE
certificate_live_dir=$LIVE_DIR
nginx_status=loaded
backup_dir=$BACKUP_DIR
renew_timer=cnnetmkt-wildcard-renew.timer
## certificate
$(sudo openssl x509 -in "$LIVE_DIR/fullchain.pem" -noout -subject -issuer -dates -ext subjectAltName)
## routes
- https://cnnetmkt.top/
- https://cnnetmkt.top/git/
- https://g.cnnetmkt.top/
- https://g.cnnetmkt.top/git/
- https://user.cnnetmkt.top/
EOF_REPORT
cd "$WORKSPACE"
chown -R aiman:aiman "$WORKSPACE/deploy/nginx" "$ROOT/artifacts" "$ROOT/logs"
runuser -u aiman -- git add deploy/nginx/cnnetmkt-wildcard-certificate.md
runuser -u aiman -- git commit -m "fix(ingress): switch cnnetmkt to wildcard certificate" || true
echo "CNNETMKT_WILDCARD_DONE status=$PROD_STATUS report=$REPORT"
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
for v in 1.22.6 1.22.5 1.22.4 1.22.3 1.22.2 1.22.1 1.22.0; do
url="https://dl.gitea.com/gitea/${v}/gitea-${v}-linux-amd64"
echo "== ${v} ${url} =="
curl -I --max-time 20 "$url" 2>&1 | sed -n '1,16p'
done
+129
View File
@@ -0,0 +1,129 @@
#!/usr/bin/env python3
from __future__ import annotations
import concurrent.futures
import json
import os
import subprocess
import sys
import time
import urllib.request
from pathlib import Path
ROOT = Path("/data/aios-gitops")
WORKSPACE = ROOT / "workspace"
AGENT_DIR = ROOT / "runtime" / "agents"
REPORT = ROOT / "artifacts" / "AIOS_V1R1C0_PARALLEL_AGENT_STATUS.json"
HERMES_EXECUTE = "http://127.0.0.1:18792/internal/hermes/execute"
def run(cmd: str, timeout: int = 90) -> dict:
p = subprocess.run(cmd, shell=True, text=True, capture_output=True, timeout=timeout)
return {
"cmd": cmd,
"returncode": p.returncode,
"stdout": p.stdout[-8000:],
"stderr": p.stderr[-8000:],
}
def hermes_plan(name: str, prompt: str) -> dict:
payload = {
"route_id": f"wx-hermes-{time.strftime('%Y%m%d-%H%M%S')}-{name[:8].replace('_','')}",
"route_target": "hermes",
"route_reason": "explicit_user_prefix",
"channel": "openclaw-weixin",
"source": "server_parallel_agent",
"tenant_id": "cnnetmkt",
"user_id": f"agent:{name}",
"user_prompt": prompt,
}
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(HERMES_EXECUTE, data=data, method="POST", headers={"Content-Type": "application/json"})
try:
with urllib.request.urlopen(req, timeout=45) as resp:
raw = resp.read().decode("utf-8", errors="replace")
return {"ok": resp.status < 300, "status": resp.status, "response": json.loads(raw or "{}")}
except Exception as exc:
return {"ok": False, "error": f"{type(exc).__name__}: {exc}"}
TASKS = {
"git_service_agent": {
"prompt": "AIOS V1R1C0 GitOps: 评估 Gitea 拉取失败后的 Git Web 服务补救方案,要求不直接暴露公网端口。",
"commands": [
"docker ps -a --format '{{.Names}} {{.Image}} {{.Status}} {{.Ports}}' | grep -E '^aios-gitea ' || true",
"docker compose -f /data/aios-gitops/adapters/gitea/docker-compose.yml ps 2>&1 || true",
"docker pull gitea/gitea:1.22 2>&1 | tail -80 || true",
"apt-cache policy cgit gitweb gitea 2>/dev/null | sed -n '1,120p' || true",
],
},
"entry_proxy_agent": {
"prompt": "AIOS V1R1C0 GitOps: 探测 cnnetmkt.top 当前入口代理,区分 NPM 与裸 nginx,并给出最小安全路由方案。",
"commands": [
"sudo ss -lntp | grep -E ':(80|443|3000|18890|18891)' || true",
"ps -ef | grep -Ei 'nginx|npm|proxy-manager|caddy|traefik' | grep -v grep || true",
"sudo nginx -T 2>/tmp/aios-nginx-t.err | grep -nE 'server_name|proxy_pass|cnnetmkt|user.cnnetmkt|git|base|model|run' | head -200 || true",
"cat /tmp/aios-nginx-t.err 2>/dev/null || true",
],
},
"gitops_api_uat_agent": {
"prompt": "AIOS V1R1C0 GitOps: 验证 GitOps API、custom LLM、priority、runtime selector 和 baseline current 状态。",
"commands": [
"curl -fsS http://127.0.0.1:18890/health || true",
"curl -fsS http://127.0.0.1:18890/api/status || true",
"TOKEN=$(head -1 /data/aios-gitops/runtime/secrets/gitops.tokens); curl -fsS -H \"Authorization: Bearer $TOKEN\" -H 'X-AIOS-User: agent-uat' -H 'X-AIOS-Role: owner' -H 'Content-Type: application/json' -d '{\"username\":\"agent-uat\",\"role\":\"owner\",\"tier\":\"ultra\"}' http://127.0.0.1:18890/api/runtime/select || true",
"TOKEN=$(head -1 /data/aios-gitops/runtime/secrets/gitops.tokens); curl -fsS -H \"Authorization: Bearer $TOKEN\" -H 'X-AIOS-User: agent-uat' -H 'X-AIOS-Role: owner' -H 'Content-Type: application/json' -d '{\"provider_name\":\"agent-local-openai-compatible\",\"base_url\":\"http://127.0.0.1:13000/v1\",\"model_name\":\"agent-test-model\",\"display_name\":\"Agent Test Model\",\"priority\":10,\"api_key_secret_ref\":\"secret://llm/agent-uat/pre-provisioned-test\"}' http://127.0.0.1:18890/api/model/custom/add || true",
"TOKEN=$(head -1 /data/aios-gitops/runtime/secrets/gitops.tokens); curl -fsS -H \"Authorization: Bearer $TOKEN\" -H 'X-AIOS-User: agent-uat' -H 'X-AIOS-Role: owner' -H 'Content-Type: application/json' -d '{\"username\":\"agent-uat\"}' http://127.0.0.1:18890/api/model/route/resolve || true",
"grep -R -E 'sk-[A-Za-z0-9_-]{20,}|AIza[0-9A-Za-z_-]{20,}|xox[baprs]-[0-9A-Za-z-]{20,}' -n /data/aios-gitops/workspace /data/aios-gitops/logs 2>/dev/null || true",
],
},
"acceptance_report_agent": {
"prompt": "AIOS V1R1C0 GitOps: 汇总当前部署证据、已完成项、阻塞项,生成验收报告更新建议。",
"commands": [
"cd /data/aios-gitops/workspace && git status --short && git log --oneline -10 && git tag | grep V1R1C0 || true",
"tail -40 /data/aios-gitops/logs/package_contract_check_v1r1c0.log; tail -40 /data/aios-gitops/logs/run_v1r1c0_acceptance.log; tail -40 /data/aios-gitops/logs/package_verify_full.log",
"systemctl is-active aios-gitops-model-api.service aios-hermes-executor.service aios-hermes-router.service openclaw-gateway.service || true",
"openclaw models status --json 2>&1 | head -120 || true",
],
},
}
def execute_agent(name: str, spec: dict) -> dict:
AGENT_DIR.mkdir(parents=True, exist_ok=True)
log_path = AGENT_DIR / f"{name}.json"
started = time.strftime("%Y-%m-%dT%H:%M:%S%z")
result = {
"name": name,
"started_at": started,
"hermes_plan": hermes_plan(name, spec["prompt"]),
"commands": [],
}
for cmd in spec["commands"]:
result["commands"].append(run(cmd))
result["finished_at"] = time.strftime("%Y-%m-%dT%H:%M:%S%z")
result["status"] = "completed"
log_path.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
return result
def main() -> int:
AGENT_DIR.mkdir(parents=True, exist_ok=True)
with concurrent.futures.ThreadPoolExecutor(max_workers=len(TASKS)) as pool:
futures = {pool.submit(execute_agent, name, spec): name for name, spec in TASKS.items()}
results = []
for future in concurrent.futures.as_completed(futures):
results.append(future.result())
summary = {
"generated_at": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"agent_count": len(results),
"agents": [{"name": r["name"], "status": r["status"], "log": str(AGENT_DIR / f"{r['name']}.json")} for r in results],
}
REPORT.write_text(json.dumps({"summary": summary, "results": results}, ensure_ascii=False, indent=2), encoding="utf-8")
print(json.dumps(summary, ensure_ascii=False, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env python3
from __future__ import annotations
import concurrent.futures
import json
import subprocess
import time
import urllib.request
from pathlib import Path
ROOT = Path("/data/aios-gitops")
AGENT_DIR = ROOT / "runtime" / "agents"
REPORT = ROOT / "artifacts" / "CNNETMKT_SSL_PARALLEL_AGENT_STATUS.json"
HERMES_EXECUTE = "http://127.0.0.1:18792/internal/hermes/execute"
def run(cmd: str, timeout: int = 90) -> dict:
p = subprocess.run(cmd, shell=True, text=True, capture_output=True, timeout=timeout)
return {
"cmd": cmd,
"returncode": p.returncode,
"stdout": p.stdout[-12000:],
"stderr": p.stderr[-12000:],
}
def hermes_plan(name: str, prompt: str) -> dict:
payload = {
"route_id": f"ssl-hermes-{time.strftime('%Y%m%d-%H%M%S')}-{name[:8]}",
"route_target": "hermes",
"route_reason": "server_ssl_ingress_validation",
"channel": "openclaw-weixin",
"source": "server_parallel_agent",
"tenant_id": "cnnetmkt",
"user_id": f"agent:{name}",
"user_prompt": prompt,
}
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(HERMES_EXECUTE, data=data, method="POST", headers={"Content-Type": "application/json"})
try:
with urllib.request.urlopen(req, timeout=45) as resp:
raw = resp.read().decode("utf-8", errors="replace")
return {"ok": resp.status < 300, "status": resp.status, "response": json.loads(raw or "{}")}
except Exception as exc:
return {"ok": False, "error": f"{type(exc).__name__}: {exc}"}
TASKS = {
"ssl_cert_agent": {
"prompt": "Validate cnnetmkt SSL certificate coverage and identify remaining wildcard/apex blockers.",
"commands": [
"certbot certificates 2>&1 | sed -n '1,160p'",
"for h in g.cnnetmkt.top cnnetmkt.top user.cnnetmkt.top; do echo --$h; echo | openssl s_client -connect 127.0.0.1:443 -servername $h 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName 2>/dev/null || true; done",
],
},
"ssl_nginx_agent": {
"prompt": "Validate Nginx routing for g.cnnetmkt.top and GitOps short links without changing config.",
"commands": [
"nginx -t 2>&1",
"sudo nginx -T 2>/dev/null | grep -n -A70 -B5 'server_name g.cnnetmkt.top' | sed -n '1,120p'",
"for h in g.cnnetmkt.top cnnetmkt.top user.cnnetmkt.top; do echo --$h; curl -k -sS -D - -o /tmp/ssl-agent-body --resolve $h:443:127.0.0.1 https://$h/ | sed -n '1,12p'; grep -ao '<title>[^<]*' /tmp/ssl-agent-body | head -1 || true; done",
],
},
"ssl_external_agent": {
"prompt": "Validate externally reachable HTTPS URLs for g.cnnetmkt.top and record cnnetmkt.top failure.",
"commands": [
"for u in https://g.cnnetmkt.top/ https://g.cnnetmkt.top/git/ https://user.cnnetmkt.top/ https://cnnetmkt.top/ https://cnnetmkt.top/git/; do echo ==$u==; curl -sS -D - -o /tmp/ssl-agent-ext --connect-timeout 20 --max-time 30 $u | sed -n '1,12p' || true; grep -ao '<title>[^<]*' /tmp/ssl-agent-ext | head -1 || true; done",
],
},
"ssl_gitops_agent": {
"prompt": "Validate GitOps repository contains the SSL ingress change and evidence report.",
"commands": [
"cd /data/aios-gitops/workspace && git status --short && git --no-pager log --oneline -8",
"cd /data/aios-gitops/workspace && test -f deploy/nginx/g-cnnetmkt-gitea-server.conf && test -f docs/ops/CNNETMKT_SSL_INGRESS_STATUS.md && echo GITOPS_SSL_DOCS_OK",
"cd /data/aios-gitops/workspace && git ls-remote --heads http://127.0.0.1:3000/aios/aios-v23.git main",
],
},
}
def execute_agent(name: str, spec: dict) -> dict:
AGENT_DIR.mkdir(parents=True, exist_ok=True)
result = {
"name": name,
"started_at": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"hermes_plan": hermes_plan(name, spec["prompt"]),
"commands": [],
}
for cmd in spec["commands"]:
result["commands"].append(run(cmd))
result["finished_at"] = time.strftime("%Y-%m-%dT%H:%M:%S%z")
result["status"] = "completed"
(AGENT_DIR / f"{name}.json").write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
return result
def main() -> int:
with concurrent.futures.ThreadPoolExecutor(max_workers=len(TASKS)) as pool:
futures = {pool.submit(execute_agent, name, spec): name for name, spec in TASKS.items()}
results = [future.result() for future in concurrent.futures.as_completed(futures)]
summary = {
"generated_at": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"agent_count": len(results),
"agents": [{"name": r["name"], "status": r["status"], "log": str(AGENT_DIR / f"{r['name']}.json")} for r in results],
}
REPORT.write_text(json.dumps({"summary": summary, "results": results}, ensure_ascii=False, indent=2), encoding="utf-8")
print(json.dumps(summary, ensure_ascii=False, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())
+4 -1
View File
@@ -5,5 +5,8 @@
"name": "MultiUser GitOps Custom LLM Baseline",
"source": "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
"update_mode": "git_patch_only",
"zip_update_mode": "deprecated_after_import"
"zip_update_mode": "deprecated",
"baseline_tag": "V1R1C0-baseline-20260706",
"git_url": "https://cnnetmkt.top/git/aios/aios-v23.git",
"updated_at": "2026-07-06T07:16:01.842715+00:00"
}