Harden workstation tier handling

This commit is contained in:
Jino Jose 2026-07-08 15:21:05 +05:30
parent 10b66569b6
commit 9a1d52230d
3 changed files with 33 additions and 12 deletions

View File

@ -1950,9 +1950,15 @@ async def readiness_report(admin: dict = Depends(admin_only)):
entitlement = _entitlement_summary(feasibility)
readiness = _readiness_score(feasibility, license_payload)
recommended_tier = (feasibility.get("recommendation") or {}).get("recommended_tier", "starter")
current_rank = list(TIER_MATRIX.keys()).index(entitlement.get("licensed_tier") or license_payload["tier"])
current_tier = entitlement.get("licensed_tier") or license_payload["tier"]
if license_payload.get("category") == CATEGORY_WORKSTATION or tier_category(current_tier) == CATEGORY_WORKSTATION:
commercial_fit = "workstation_category"
commercial_fit_note = "Workstation is a standalone product category, so Server S/M/L/Max upgrade guidance does not apply directly."
else:
current_rank = list(TIER_MATRIX.keys()).index(current_tier)
recommended_rank = list(TIER_MATRIX.keys()).index(_normalize_tier(recommended_tier))
commercial_fit = "matched" if current_rank >= recommended_rank else "license_upgrade_recommended"
commercial_fit_note = "Current license covers the recommended deployment." if commercial_fit == "matched" else "Quote a higher tier or reduce enabled features for this hardware."
return {
"schema": "cezen.readiness_report.v1",
"generated_at": utcnow(),
@ -1963,10 +1969,10 @@ async def readiness_report(admin: dict = Depends(admin_only)):
"readiness": readiness,
"commercial_fit": {
"status": commercial_fit,
"current_tier": entitlement.get("licensed_tier") or license_payload["tier"],
"current_tier": current_tier,
"provisioned_tier": entitlement.get("provisioned_tier"),
"recommended_tier": _normalize_tier(recommended_tier),
"note": "Current license covers the recommended deployment." if commercial_fit == "matched" else "Quote a higher tier or reduce enabled features for this hardware.",
"note": commercial_fit_note,
},
"proposal_summary": [
f"Recommended Cezen profile: {(feasibility.get('recommendation') or {}).get('recommended_profile', 'core')}",
@ -2070,6 +2076,10 @@ async def get_branding():
result["license_support_until"] = license_record.get("support_until", "")
result["license_status"] = entitlement.get("license_status", "missing")
result["provisioned_tier"] = entitlement.get("provisioned_tier", "")
tier = result.get("tier_slug")
if tier in TIER_MATRIX:
result["tier_commercial_label"] = TIER_MATRIX[tier].get("commercial_label", TIER_MATRIX[tier]["label"])
result["tier_category"] = TIER_MATRIX[tier].get("category", CATEGORY_SERVER)
return result
@app.put("/api/settings/branding")

View File

@ -399,10 +399,10 @@ python3 - <<'PY'
import json, os, time
# NOTE: install.sh (Phase 2) rewrites /opt/cezen/install-record.json after
# this, using its own $TIER routing value ("starter" for Workstation) — this
# is expected: provisioned_tier there reflects the Ansible profile actually
# installed. The persistent Workstation marker is /opt/cezen/tier, not this
# file, and install.sh never touches that marker.
# this. For Workstation, it preserves category="workstation" and selected_tier
# = "workstation", while provisioned_tier becomes "starter" to reflect the
# Ansible profile actually installed. The persistent Workstation marker is
# still /opt/cezen/tier, and install.sh never touches that marker.
payload = {
"schema": "cezen.install_record.v1",
"customer_name": os.environ.get("CUSTOMER_NAME", "").strip(),

View File

@ -22,6 +22,8 @@ elif [ -f /opt/aipackage/autoinstall/.tier ]; then
else
TIER="basic" # default if no marker found
fi
DISPLAY_TIER="$TIER"
PRODUCT_CATEGORY="server"
PHASE="1"
SKIP_ROLES=""
SOFTWARE_ONLY=false
@ -55,11 +57,19 @@ done
normalize_tier() {
case "$TIER" in
workstation)
DISPLAY_TIER="workstation"
PRODUCT_CATEGORY="workstation"
TIER="starter"
;;
entry|basic) TIER="basic" ;;
mid|pro) TIER="pro" ;;
advanced|max) TIER="max" ;;
starter) TIER="starter" ;;
esac
if [ "$PRODUCT_CATEGORY" = "server" ]; then
DISPLAY_TIER="$TIER"
fi
}
normalize_tier
@ -191,7 +201,7 @@ PY
}
write_install_record() {
python3 - "$INSTALL_RECORD_JSON" "$TIER" "$PROFILE" "$SKIP_ROLES" "$GPU_AVAILABLE" "$FEASIBILITY_JSON" "$LICENSE_EVAL_JSON" <<'PY'
python3 - "$INSTALL_RECORD_JSON" "$TIER" "$PROFILE" "$SKIP_ROLES" "$GPU_AVAILABLE" "$FEASIBILITY_JSON" "$LICENSE_EVAL_JSON" "$DISPLAY_TIER" "$PRODUCT_CATEGORY" <<'PY'
import json, sys
from datetime import datetime, timezone
from pathlib import Path
@ -226,8 +236,9 @@ components = {
payload = {
"schema": "cezen.install_record.v1",
"generated_at": datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z"),
"selected_tier": tier,
"selected_tier": sys.argv[8],
"provisioned_tier": tier,
"category": sys.argv[9],
"provisioned_profile": profile,
"skip_roles": skip_roles,
"components": components,
@ -413,7 +424,7 @@ run_phase2() {
echo ""
echo "╔══════════════════════════════════════════╗"
echo "║ Nexus One AI installation complete! ║"
echo "║ Tier: $(printf '%-33s' "$TIER")"
echo "║ Tier: $(printf '%-33s' "$DISPLAY_TIER")"
echo "║ ║"
echo "║ Portal → http://localhost ║"
echo "║ Ollama API → http://localhost:11434 ║"