      * PUBLIC DOMAIN - NO LICENSE, NO WARRANTY
      *
      * This is free public domain software for the public good of a permacomputer hosted
      * at permacomputer.com - an always-on computer by the people, for the people. One
      * which is durable, easy to repair, and distributed like tap water for machine
      * learning intelligence.
      *
      * The permacomputer is community-owned infrastructure optimized around four values:
      *
      *   TRUTH    - First principles, math & science, open source code freely distributed
      *   FREEDOM  - Voluntary partnerships, freedom from tyranny & corporate control
      *   HARMONY  - Minimal waste, self-renewing systems with diverse thriving connections
      *   LOVE     - Be yourself without hurting others, cooperation through natural law
      *
      * This software contributes to that vision by enabling code execution across 42+
      * programming languages through a unified interface, accessible to all. Code is
      * seeds to sprout on any abandoned technology.
      *
      * Learn more: https://www.permacomputer.com
      *
      * Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
      * software, either in source code form or as a compiled binary, for any purpose,
      * commercial or non-commercial, and by any means.
      *
      * NO WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
      *
      * That said, our permacomputer's digital membrane stratum continuously runs unit,
      * integration, and functional tests on all of it's own software - with our
      * permacomputer monitoring itself, repairing itself, with minimal human in the
      * loop guidance. Our agents do their best.
      *
      * Copyright 2025 TimeHexOn & foxhop & russell@unturf
      * https://www.timehexon.com
      * https://www.foxhop.net
      * https://www.unturf.com/software


       IDENTIFICATION DIVISION.
       PROGRAM-ID. UNSANDBOX-CLI.
       AUTHOR. UNSANDBOX.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT SOURCE-FILE ASSIGN TO WS-FILENAME
               ORGANIZATION IS LINE SEQUENTIAL
               FILE STATUS IS WS-FILE-STATUS.

       DATA DIVISION.
       FILE SECTION.
       FD  SOURCE-FILE.
       01  SOURCE-LINE         PIC X(1024).

       WORKING-STORAGE SECTION.
       01  WS-FILENAME         PIC X(256).
       01  WS-FILE-STATUS      PIC XX.
       01  WS-API-KEY          PIC X(256).
       01  WS-PUBLIC-KEY       PIC X(256).
       01  WS-SECRET-KEY       PIC X(256).
       01  WS-LANGUAGE         PIC X(32).
       01  WS-EXTENSION        PIC X(16).
       01  WS-CURL-CMD         PIC X(4096).
       01  WS-EXIT-CODE        PIC 9(4) VALUE 0.
       01  WS-DOT-POS          PIC 9(4) VALUE 0.
       01  WS-LEN              PIC 9(4) VALUE 0.
       01  WS-I                PIC 9(4) VALUE 0.
       01  WS-ARG1             PIC X(256).
       01  WS-ARG2             PIC X(256).
       01  WS-ARG3             PIC X(256).
       01  WS-COMMAND          PIC X(32).
       01  WS-OPERATION        PIC X(32).
       01  WS-ID               PIC X(256).
       01  WS-NAME             PIC X(256).
       01  WS-PORTS            PIC X(256).
       01  WS-DOMAINS          PIC X(256).
       01  WS-SERVICE-TYPE     PIC X(64).
       01  WS-BOOTSTRAP        PIC X(2048).
       01  WS-BOOTSTRAP-FILE   PIC X(256).
       01  WS-INPUT-FILES      PIC X(1024).
       01  WS-PORTAL-BASE      PIC X(256) VALUE
           "https://unsandbox.com".
       01  WS-LANGUAGES-CACHE-TTL PIC 9(8) VALUE 3600.
       01  WS-EXTEND-FLAG      PIC X(8).
       01  WS-SVC-ENVS         PIC X(2048).
       01  WS-SVC-ENV-FILE     PIC X(256).
       01  WS-ENV-ACTION       PIC X(32).
       01  WS-ENV-TARGET       PIC X(256).
       01  WS-VCPU             PIC 9(2) VALUE 0.
       01  WS-VCPU-STR         PIC X(8).
       01  WS-RAM              PIC 9(4) VALUE 0.
       01  WS-JSON-OUTPUT      PIC X(8).
       01  WS-IMAGE-SOURCE-TYPE PIC X(32).
       01  WS-IMAGE-VISIBILITY PIC X(32).
       01  WS-ARG4             PIC X(256).
       01  WS-ARG5             PIC X(256).
       01  WS-UNFREEZE-ON-DEMAND PIC X(8).
       01  WS-UOD-ENABLED      PIC X(8).
       01  WS-TYPE             PIC X(32).
       01  WS-SHELL            PIC X(32).

       PROCEDURE DIVISION.
       MAIN-PROCEDURE.
      * Get command line argument (first argument)
           ACCEPT WS-ARG1 FROM COMMAND-LINE.

           IF WS-ARG1 = SPACES
               DISPLAY "Usage: un.cob <source_file>" UPON SYSERR
               DISPLAY "       un.cob session [options]" UPON SYSERR
               DISPLAY "       un.cob service [options]" UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Check for subcommands
           IF WS-ARG1 = "session"
               PERFORM HANDLE-SESSION
               STOP RUN
           END-IF.

           IF WS-ARG1 = "service"
               PERFORM HANDLE-SERVICE
               STOP RUN
           END-IF.

           IF WS-ARG1 = "key"
               PERFORM HANDLE-KEY
               STOP RUN
           END-IF.

           IF WS-ARG1 = "languages"
               PERFORM HANDLE-LANGUAGES
               STOP RUN
           END-IF.

           IF WS-ARG1 = "image"
               PERFORM HANDLE-IMAGE
               STOP RUN
           END-IF.

           IF WS-ARG1 = "snapshot"
               PERFORM HANDLE-SNAPSHOT
               STOP RUN
           END-IF.

      * Default: execute command
           MOVE WS-ARG1 TO WS-FILENAME.
           PERFORM HANDLE-EXECUTE.
           STOP RUN.

       HANDLE-EXECUTE.
      * Check if file exists
           OPEN INPUT SOURCE-FILE.
           IF WS-FILE-STATUS NOT = "00"
               DISPLAY "Error: File not found: " WS-FILENAME
                   UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.
           CLOSE SOURCE-FILE.

      * Detect language from extension
           PERFORM DETECT-LANGUAGE.

           IF WS-LANGUAGE = "unknown"
               DISPLAY "Error: Unknown language for file: "
                   WS-FILENAME UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Get API key from environment
           ACCEPT WS-API-KEY FROM ENVIRONMENT "UNSANDBOX_API_KEY".

           IF WS-API-KEY = SPACES
               DISPLAY "Error: UNSANDBOX_API_KEY not set" UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Use curl to make request
           PERFORM MAKE-EXECUTE-REQUEST.

       HANDLE-SESSION.
      * Get API key
           ACCEPT WS-API-KEY FROM ENVIRONMENT "UNSANDBOX_API_KEY".
           IF WS-API-KEY = SPACES
               DISPLAY "Error: UNSANDBOX_API_KEY not set" UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Initialize session parameters
           MOVE SPACES TO WS-INPUT-FILES.

      * Parse session arguments (simplified)
      * For full implementation, would need to parse multiple args
           ACCEPT WS-ARG2 FROM ARGUMENT-VALUE.

           IF WS-ARG2 = "-l" OR WS-ARG2 = "--list"
               PERFORM SESSION-LIST
           ELSE
               IF WS-ARG2 = "--kill"
                   ACCEPT WS-ID FROM ARGUMENT-VALUE
                   PERFORM SESSION-KILL
               ELSE
                   PERFORM PARSE-SESSION-CREATE-ARGS
                   PERFORM SESSION-CREATE
               END-IF
           END-IF.

       HANDLE-SERVICE.
      * Get API keys (try new format first, fall back to old)
           ACCEPT WS-PUBLIC-KEY FROM ENVIRONMENT "UNSANDBOX_PUBLIC_KEY".
           IF WS-PUBLIC-KEY NOT = SPACES
               ACCEPT WS-SECRET-KEY FROM ENVIRONMENT "UNSANDBOX_SECRET_KEY"
               IF WS-SECRET-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_SECRET_KEY not set"
                       UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
           ELSE
               ACCEPT WS-API-KEY FROM ENVIRONMENT "UNSANDBOX_API_KEY"
               IF WS-API-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_PUBLIC_KEY/SECRET_KEY or "
                       "UNSANDBOX_API_KEY not set" UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
               MOVE WS-API-KEY TO WS-PUBLIC-KEY
               MOVE WS-API-KEY TO WS-SECRET-KEY
           END-IF.

      * Initialize service parameters
           MOVE SPACES TO WS-NAME.
           MOVE SPACES TO WS-PORTS.
           MOVE SPACES TO WS-DOMAINS.
           MOVE SPACES TO WS-SERVICE-TYPE.
           MOVE SPACES TO WS-BOOTSTRAP.
           MOVE SPACES TO WS-BOOTSTRAP-FILE.
           MOVE SPACES TO WS-INPUT-FILES.
           MOVE SPACES TO WS-SVC-ENVS.
           MOVE SPACES TO WS-SVC-ENV-FILE.
           MOVE SPACES TO WS-ENV-ACTION.
           MOVE SPACES TO WS-ENV-TARGET.

      * Parse service arguments
           ACCEPT WS-ARG2 FROM ARGUMENT-VALUE.

           IF WS-ARG2 = "-l" OR WS-ARG2 = "--list"
               PERFORM SERVICE-LIST
           ELSE IF WS-ARG2 = "env"
               ACCEPT WS-ENV-ACTION FROM ARGUMENT-VALUE
               ACCEPT WS-ENV-TARGET FROM ARGUMENT-VALUE
               PERFORM PARSE-SERVICE-ENV-ARGS
               PERFORM SERVICE-ENV
           ELSE IF WS-ARG2 = "--info"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM SERVICE-INFO
           ELSE IF WS-ARG2 = "--logs"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM SERVICE-LOGS
           ELSE IF WS-ARG2 = "--freeze"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM SERVICE-SLEEP
           ELSE IF WS-ARG2 = "--unfreeze"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM SERVICE-WAKE
           ELSE IF WS-ARG2 = "--destroy"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM SERVICE-DESTROY
           ELSE IF WS-ARG2 = "--dump-bootstrap"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM SERVICE-DUMP-BOOTSTRAP
           ELSE IF WS-ARG2 = "--resize"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM PARSE-SERVICE-RESIZE-ARGS
               PERFORM SERVICE-RESIZE
           ELSE IF WS-ARG2 = "--set-unfreeze-on-demand"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM PARSE-SERVICE-UOD-ARGS
               PERFORM SERVICE-SET-UNFREEZE-ON-DEMAND
           ELSE IF WS-ARG2 = "--name"
               ACCEPT WS-NAME FROM ARGUMENT-VALUE
               PERFORM PARSE-SERVICE-CREATE-ARGS
               PERFORM SERVICE-CREATE
           ELSE
               DISPLAY "Error: Use --list, --info, --logs, "
                   "--freeze, --unfreeze, --destroy, --dump-bootstrap, "
                   "--resize, --set-unfreeze-on-demand, --name, or env"
                   UPON SYSERR
               MOVE 1 TO RETURN-CODE
           END-IF.

       DETECT-LANGUAGE.
      * Find last dot in filename
           MOVE FUNCTION LENGTH(FUNCTION TRIM(WS-FILENAME)) TO WS-LEN.
           MOVE 0 TO WS-DOT-POS.
           PERFORM VARYING WS-I FROM WS-LEN BY -1
               UNTIL WS-I < 1 OR WS-DOT-POS > 0
               IF WS-FILENAME(WS-I:1) = "."
                   MOVE WS-I TO WS-DOT-POS
               END-IF
           END-PERFORM.

           IF WS-DOT-POS = 0
               MOVE "unknown" TO WS-LANGUAGE
           ELSE
               COMPUTE WS-I = WS-LEN - WS-DOT-POS + 1
               MOVE WS-FILENAME(WS-DOT-POS:WS-I) TO WS-EXTENSION

               EVALUATE WS-EXTENSION
                   WHEN ".jl"     MOVE "julia"      TO WS-LANGUAGE
                   WHEN ".r"      MOVE "r"          TO WS-LANGUAGE
                   WHEN ".cr"     MOVE "crystal"    TO WS-LANGUAGE
                   WHEN ".f90"    MOVE "fortran"    TO WS-LANGUAGE
                   WHEN ".cob"    MOVE "cobol"      TO WS-LANGUAGE
                   WHEN ".pro"    MOVE "prolog"     TO WS-LANGUAGE
                   WHEN ".forth"  MOVE "forth"      TO WS-LANGUAGE
                   WHEN ".4th"    MOVE "forth"      TO WS-LANGUAGE
                   WHEN ".py"     MOVE "python"     TO WS-LANGUAGE
                   WHEN ".js"     MOVE "javascript" TO WS-LANGUAGE
                   WHEN ".rb"     MOVE "ruby"       TO WS-LANGUAGE
                   WHEN ".go"     MOVE "go"         TO WS-LANGUAGE
                   WHEN ".rs"     MOVE "rust"       TO WS-LANGUAGE
                   WHEN ".c"      MOVE "c"          TO WS-LANGUAGE
                   WHEN ".cpp"    MOVE "cpp"        TO WS-LANGUAGE
                   WHEN ".java"   MOVE "java"       TO WS-LANGUAGE
                   WHEN ".sh"     MOVE "bash"       TO WS-LANGUAGE
                   WHEN OTHER     MOVE "unknown"    TO WS-LANGUAGE
               END-EVALUATE
           END-IF.

       MAKE-EXECUTE-REQUEST.
      * Get public/secret keys with fallback
           ACCEPT WS-PUBLIC-KEY FROM ENVIRONMENT "UNSANDBOX_PUBLIC_KEY".
           IF WS-PUBLIC-KEY NOT = SPACES
               ACCEPT WS-SECRET-KEY FROM ENVIRONMENT "UNSANDBOX_SECRET_KEY"
               IF WS-SECRET-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_SECRET_KEY not set"
                       UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
           ELSE
               ACCEPT WS-PUBLIC-KEY FROM ENVIRONMENT "UNSANDBOX_API_KEY"
               IF WS-PUBLIC-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_PUBLIC_KEY/SECRET_KEY or "
                       "UNSANDBOX_API_KEY not set" UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
               MOVE WS-PUBLIC-KEY TO WS-SECRET-KEY
           END-IF.

      * Build curl command using shell with HMAC signature
           STRING "TS=$(date +%s); "
               "BODY=$(jq -Rs '{language: """
               FUNCTION TRIM(WS-LANGUAGE)
               """, code: .}' < '"
               FUNCTION TRIM(WS-FILENAME)
               "'); "
               "SIG=$(echo -n \"$TS:POST:/execute:$BODY\" | "
               "openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP=$(curl -s -w '\n%{http_code}' -X POST "
               "https://api.unsandbox.com/execute "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "--data-binary \"$BODY\"); "
               "HTTP_CODE=$(echo \"$RESP\" | tail -n1); "
               "BODY=$(echo \"$RESP\" | sed '$d'); "
               "echo \"$BODY\" > /tmp/unsandbox_resp.json; "
               "if echo \"$BODY\" | grep -q '\"timestamp\"' && "
               "(echo \"$HTTP_CODE\" | grep -q '401' || "
               "echo \"$BODY\" | grep -qi 'expired' || "
               "echo \"$BODY\" | grep -qi 'invalid'); then "
               "echo -e '\x1b[31mError: Request timestamp expired "
               "(must be within 5 minutes of server time)\x1b[0m' >&2; "
               "echo -e '\x1b[33mYour computer'"'"'s clock may have "
               "drifted.\x1b[0m' >&2; "
               "echo 'Check your system time and sync with NTP if "
               "needed:' >&2; "
               "echo '  Linux:   sudo ntpdate -s time.nist.gov' >&2; "
               "echo '  macOS:   sudo sntp -sS time.apple.com' >&2; "
               "echo '  Windows: w32tm /resync' >&2; "
               "rm -f /tmp/unsandbox_resp.json; exit 1; fi; "
               "jq -r '.stdout // empty' /tmp/unsandbox_resp.json | "
               "sed 's/^/\x1b[34m/' | sed 's/$/\x1b[0m/'; "
               "jq -r '.stderr // empty' /tmp/unsandbox_resp.json | "
               "sed 's/^/\x1b[31m/' | sed 's/$/\x1b[0m/' >&2; "
               "rm -f /tmp/unsandbox_resp.json"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD
               RETURNING WS-EXIT-CODE.

           MOVE WS-EXIT-CODE TO RETURN-CODE.

       SESSION-LIST.
           STRING "curl -s -X GET https://api.unsandbox.com/sessions "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' | jq -r '.sessions[] | "
               '"\(.id) \(.shell) \(.status) \(.created_at)"'' "
               "2>/dev/null || echo 'No active sessions'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SESSION-KILL.
           STRING "curl -s -X DELETE "
               "https://api.unsandbox.com/sessions/"
               FUNCTION TRIM(WS-ID) " "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' >/dev/null && "
               "echo -e '\x1b[32mSession terminated: "
               FUNCTION TRIM(WS-ID) "\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-SESSION-CREATE-ARGS.
      * Parse arguments for session creation
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "-f"
                   ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
                   IF WS-INPUT-FILES NOT = SPACES
                       STRING FUNCTION TRIM(WS-INPUT-FILES) ","
                           FUNCTION TRIM(WS-ARG3)
                           DELIMITED BY SIZE INTO WS-INPUT-FILES
                       END-STRING
                   ELSE
                       MOVE WS-ARG3 TO WS-INPUT-FILES
                   END-IF
               ELSE
                   IF WS-ARG3(1:1) = "-"
                       STRING "Unknown option: " FUNCTION TRIM(WS-ARG3)
                           DELIMITED BY SIZE INTO WS-ERROR-MSG
                       END-STRING
                       DISPLAY WS-ERROR-MSG UPON SYSERR
                       DISPLAY "Usage: un.cob session [options]" UPON SYSERR
                       MOVE 1 TO RETURN-CODE
                       STOP RUN
                   END-IF
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       SESSION-CREATE.
      * Build curl command for session creation with input_files support
           STRING "INPUT_FILES=''; "
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           IF WS-INPUT-FILES NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "IFS=',' read -ra FILES <<< '"
                   FUNCTION TRIM(WS-INPUT-FILES)
                   "'; "
                   "for f in \"${FILES[@]}\"; do "
                   "b64=$(base64 -w0 \"$f\" 2>/dev/null || base64 \"$f\"); "
                   "name=$(basename \"$f\"); "
                   "if [ -n \"$INPUT_FILES\" ]; then INPUT_FILES=\"$INPUT_FILES,\"; fi; "
                   "INPUT_FILES=\"$INPUT_FILES{\\\"filename\\\":\\\"$name\\\",\\\"content\\\":\\\"$b64\\\"}\"; "
                   "done; "
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           STRING FUNCTION TRIM(WS-CURL-CMD)
               "if [ -n \"$INPUT_FILES\" ]; then "
               "JSON='{\"shell\":\"bash\",\"input_files\":['\"$INPUT_FILES\"']}'; "
               "else JSON='{\"shell\":\"bash\"}'; fi; "
               "curl -s -X POST https://api.unsandbox.com/sessions "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' -d \"$JSON\" && "
               "echo -e '\x1b[33mSession created (WebSocket required)\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-LIST.
           STRING "curl -s -X GET https://api.unsandbox.com/services "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' | jq -r '.services[] | "
               '"\(.id) \(.name) \(.status)"'' "
               "2>/dev/null || echo 'No services'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-INFO.
           STRING "curl -s -X GET "
               "https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID) " "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' | jq ."
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-LOGS.
           STRING "curl -s -X GET "
               "https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID) "/logs "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' | jq -r '.logs'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-SLEEP.
           STRING "curl -s -X POST "
               "https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID) "/freeze "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' >/dev/null && "
               "echo -e '\x1b[32mService frozen: "
               FUNCTION TRIM(WS-ID) "\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-WAKE.
           STRING "curl -s -X POST "
               "https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID) "/unfreeze "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' >/dev/null && "
               "echo -e '\x1b[32mService unfreezing: "
               FUNCTION TRIM(WS-ID) "\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-DESTROY.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:DELETE:/services/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP=$(curl -s -w '\\n%{http_code}' -X DELETE "
               "'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG); "
               "HTTP_CODE=$(echo \"$RESP\" | tail -n1); "
               "BODY=$(echo \"$RESP\" | sed '$d'); "
               "if [ \"$HTTP_CODE\" = \"428\" ]; then "
               "CHALLENGE_ID=$(echo \"$BODY\" | jq -r '.challenge_id // empty'); "
               "echo -e '\\x1b[33mConfirmation required. Check your email "
               "for a one-time code.\\x1b[0m' >&2; "
               "echo -n 'Enter OTP: ' >&2; read OTP; "
               "if [ -z \"$OTP\" ]; then "
               "echo -e '\\x1b[31mError: Operation cancelled\\x1b[0m' >&2; "
               "exit 1; fi; "
               "TS2=$(date +%s); "
               "SIG2=$(echo -n \"$TS2:DELETE:/services/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP2=$(curl -s -w '\\n%{http_code}' -X DELETE "
               "'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS2 "
               "-H 'X-Signature: '$SIG2 "
               "-H 'X-Sudo-OTP: '$OTP "
               "-H 'X-Sudo-Challenge: '$CHALLENGE_ID); "
               "HTTP_CODE2=$(echo \"$RESP2\" | tail -n1); "
               "if [ \"$HTTP_CODE2\" = \"200\" ] || "
               "[ \"$HTTP_CODE2\" = \"204\" ]; then "
               "echo -e '\\x1b[32mService destroyed: "
               FUNCTION TRIM(WS-ID) "\\x1b[0m'; "
               "else echo \"$RESP2\" | sed '$d' | jq . 2>/dev/null || "
               "echo \"$RESP2\" | sed '$d'; exit 1; fi; "
               "elif [ \"$HTTP_CODE\" = \"200\" ] || "
               "[ \"$HTTP_CODE\" = \"204\" ]; then "
               "echo -e '\\x1b[32mService destroyed: "
               FUNCTION TRIM(WS-ID) "\\x1b[0m'; "
               "else echo \"$BODY\" | jq . 2>/dev/null || "
               "echo \"$BODY\"; exit 1; fi"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-DUMP-BOOTSTRAP.
      * Check if WS-ARG3 contains --dump-file argument
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           MOVE SPACES TO WS-BOOTSTRAP.
           IF WS-ARG3 = "--dump-file"
               ACCEPT WS-BOOTSTRAP FROM ARGUMENT-VALUE
           END-IF.

           STRING "echo 'Fetching bootstrap script from "
               FUNCTION TRIM(WS-ID) "...' >&2; "
               "RESP=$(curl -s -X POST "
               "https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID) "/execute "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' -d '{\"command\":\"cat /tmp/bootstrap.sh\"}'); "
               "STDOUT=$(echo \"$RESP\" | jq -r '.stdout // empty'); "
               "if [ -n \"$STDOUT\" ]; then "
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           IF WS-BOOTSTRAP NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "echo \"$STDOUT\" > '"
                   FUNCTION TRIM(WS-BOOTSTRAP)
                   "' && chmod 755 '"
                   FUNCTION TRIM(WS-BOOTSTRAP)
                   "' && echo 'Bootstrap saved to "
                   FUNCTION TRIM(WS-BOOTSTRAP) "'; "
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           ELSE
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "echo \"$STDOUT\"; "
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           STRING FUNCTION TRIM(WS-CURL-CMD)
               "else echo -e '\x1b[31mError: Failed to fetch "
               "bootstrap\x1b[0m' >&2; exit 1; fi"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-SERVICE-CREATE-ARGS.
      * Parse remaining arguments for service creation
      * This is a simplified parser that looks for specific flags
           MOVE SPACES TO WS-UNFREEZE-ON-DEMAND.
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "--ports"
                   ACCEPT WS-PORTS FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--domains"
                   ACCEPT WS-DOMAINS FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--type"
                   ACCEPT WS-SERVICE-TYPE FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--bootstrap"
                   ACCEPT WS-BOOTSTRAP FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--bootstrap-file"
                   ACCEPT WS-BOOTSTRAP-FILE FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--unfreeze-on-demand"
                   ACCEPT WS-UNFREEZE-ON-DEMAND FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "-e"
                   ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
                   IF WS-SVC-ENVS NOT = SPACES
                       STRING FUNCTION TRIM(WS-SVC-ENVS) X"0A"
                           FUNCTION TRIM(WS-ARG3)
                           DELIMITED BY SIZE INTO WS-SVC-ENVS
                       END-STRING
                   ELSE
                       MOVE WS-ARG3 TO WS-SVC-ENVS
                   END-IF
               ELSE IF WS-ARG3 = "--env-file"
                   ACCEPT WS-SVC-ENV-FILE FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "-f"
                   ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
                   IF WS-INPUT-FILES NOT = SPACES
                       STRING FUNCTION TRIM(WS-INPUT-FILES) ","
                           FUNCTION TRIM(WS-ARG3)
                           DELIMITED BY SIZE INTO WS-INPUT-FILES
                       END-STRING
                   ELSE
                       MOVE WS-ARG3 TO WS-INPUT-FILES
                   END-IF
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       PARSE-SERVICE-ENV-ARGS.
      * Parse -e and --env-file for env set command
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "-e"
                   ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
                   IF WS-SVC-ENVS NOT = SPACES
                       STRING FUNCTION TRIM(WS-SVC-ENVS) X"0A"
                           FUNCTION TRIM(WS-ARG3)
                           DELIMITED BY SIZE INTO WS-SVC-ENVS
                       END-STRING
                   ELSE
                       MOVE WS-ARG3 TO WS-SVC-ENVS
                   END-IF
               ELSE IF WS-ARG3 = "--env-file"
                   ACCEPT WS-SVC-ENV-FILE FROM ARGUMENT-VALUE
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       SERVICE-ENV.
      * Handle env subcommand (status/set/export/delete)
           IF WS-ENV-ACTION = "status"
               PERFORM SERVICE-ENV-STATUS
           ELSE IF WS-ENV-ACTION = "set"
               PERFORM SERVICE-ENV-SET
           ELSE IF WS-ENV-ACTION = "export"
               PERFORM SERVICE-ENV-EXPORT
           ELSE IF WS-ENV-ACTION = "delete"
               PERFORM SERVICE-ENV-DELETE
           ELSE
               DISPLAY "Error: Unknown env action: "
                   FUNCTION TRIM(WS-ENV-ACTION) UPON SYSERR
               DISPLAY "Usage: un.cob service env "
                   "<status|set|export|delete> <service_id>" UPON SYSERR
               MOVE 1 TO RETURN-CODE
           END-IF.

       SERVICE-ENV-STATUS.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:GET:/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env:\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X GET 'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG | jq ."
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-ENV-SET.
           STRING "ENV_CONTENT=''; "
               "ENV_LINES='"
               FUNCTION TRIM(WS-SVC-ENVS)
               "'; "
               "if [ -n \"$ENV_LINES\" ]; then "
               "ENV_CONTENT=\"$ENV_LINES\"; fi; "
               "ENV_FILE='"
               FUNCTION TRIM(WS-SVC-ENV-FILE)
               "'; "
               "if [ -n \"$ENV_FILE\" ] && [ -f \"$ENV_FILE\" ]; then "
               "while IFS= read -r line || [ -n \"$line\" ]; do "
               "case \"$line\" in \"#\"*|\"\") continue ;; esac; "
               "if [ -n \"$ENV_CONTENT\" ]; then "
               "ENV_CONTENT=\"$ENV_CONTENT"
               X"0A"
               "\"; fi; "
               "ENV_CONTENT=\"$ENV_CONTENT$line\"; "
               "done < \"$ENV_FILE\"; fi; "
               "if [ -z \"$ENV_CONTENT\" ]; then "
               "echo -e '\x1b[31mError: No environment variables "
               "to set\x1b[0m' >&2; exit 1; fi; "
               "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:PUT:/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env:$ENV_CONTENT\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X PUT 'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-H 'Content-Type: text/plain' "
               "--data-binary \"$ENV_CONTENT\" | jq ."
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-ENV-EXPORT.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:POST:/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env/export:\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env/export' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG | jq -r '.content // empty'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-ENV-DELETE.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:DELETE:/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env:\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X DELETE 'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ENV-TARGET)
               "/env' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG >/dev/null && "
               "echo -e '\x1b[32mVault deleted for: "
               FUNCTION TRIM(WS-ENV-TARGET)
               "\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SERVICE-CREATE.
      * Build service creation with HMAC auth and auto-vault
           STRING "BODY='{\"name\":\"" FUNCTION TRIM(WS-NAME) "\""
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

      * Add ports if provided
           IF WS-PORTS NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"ports\":[" FUNCTION TRIM(WS-PORTS) "]"
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

      * Add domains if provided
           IF WS-DOMAINS NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"domains\":[\"" FUNCTION TRIM(WS-DOMAINS) "\"]"
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

      * Add service_type if provided
           IF WS-SERVICE-TYPE NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"service_type\":\"" FUNCTION TRIM(WS-SERVICE-TYPE) "\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

      * Add bootstrap if provided
           IF WS-BOOTSTRAP NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"bootstrap\":\"" FUNCTION TRIM(WS-BOOTSTRAP) "\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

      * Add unfreeze_on_demand if provided
           IF WS-UNFREEZE-ON-DEMAND NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"unfreeze_on_demand\":"
                   FUNCTION TRIM(WS-UNFREEZE-ON-DEMAND)
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

      * Close JSON body
           STRING FUNCTION TRIM(WS-CURL-CMD) "}'; "
               "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:POST:/services:$BODY\" | "
               "openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP=$(curl -s -X POST https://api.unsandbox.com/services "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-PUBLIC-KEY) "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\"); "
               "SVC_ID=$(echo \"$RESP\" | jq -r '.id // empty'); "
               "if [ -n \"$SVC_ID\" ]; then "
               "echo -e '\x1b[32m'\"$SVC_ID\"' created\x1b[0m'; "
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

      * Add auto-vault logic
           STRING FUNCTION TRIM(WS-CURL-CMD)
               "ENV_CONTENT=''; "
               "ENV_LINES='" FUNCTION TRIM(WS-SVC-ENVS) "'; "
               "if [ -n \"$ENV_LINES\" ]; then ENV_CONTENT=\"$ENV_LINES\"; fi; "
               "ENV_FILE='" FUNCTION TRIM(WS-SVC-ENV-FILE) "'; "
               "if [ -n \"$ENV_FILE\" ] && [ -f \"$ENV_FILE\" ]; then "
               "while IFS= read -r line || [ -n \"$line\" ]; do "
               "case \"$line\" in \"#\"*|\"\") continue ;; esac; "
               "if [ -n \"$ENV_CONTENT\" ]; then "
               "ENV_CONTENT=\"$ENV_CONTENT" X"0A" "\"; fi; "
               "ENV_CONTENT=\"$ENV_CONTENT$line\"; "
               "done < \"$ENV_FILE\"; fi; "
               "if [ -n \"$ENV_CONTENT\" ]; then "
               "TS2=$(date +%s); "
               "SIG2=$(echo -n \"$TS2:PUT:/services/$SVC_ID/env:$ENV_CONTENT\" | "
               "openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X PUT \"https://api.unsandbox.com/services/$SVC_ID/env\" "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-PUBLIC-KEY) "' "
               "-H 'X-Timestamp: '$TS2 "
               "-H 'X-Signature: '$SIG2 "
               "-H 'Content-Type: text/plain' "
               "--data-binary \"$ENV_CONTENT\" >/dev/null && "
               "echo -e '\x1b[32mVault configured\x1b[0m'; fi; "
               "else echo \"$RESP\" | jq .; fi"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       HANDLE-KEY.
      * Get API key
           ACCEPT WS-API-KEY FROM ENVIRONMENT "UNSANDBOX_API_KEY".
           IF WS-API-KEY = SPACES
               DISPLAY "Error: UNSANDBOX_API_KEY not set" UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Parse key arguments
           MOVE SPACES TO WS-EXTEND-FLAG.
           ACCEPT WS-ARG2 FROM ARGUMENT-VALUE.

           IF WS-ARG2 = "--extend"
               MOVE "true" TO WS-EXTEND-FLAG
           END-IF.

      * Validate key
           PERFORM VALIDATE-KEY.

       VALIDATE-KEY.
      * Build curl command to validate API key
           STRING "curl -s -X POST "
               FUNCTION TRIM(WS-PORTAL-BASE)
               "/keys/validate "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-API-KEY)
               "' -o /tmp/unsandbox_key_resp.json; "
               "STATUS=$?; "
               "if [ $STATUS -ne 0 ]; then "
               "echo -e '\x1b[31mInvalid\x1b[0m'; "
               "exit 1; "
               "fi; "
               "EXPIRED=$(jq -r '.expired // false' "
               "/tmp/unsandbox_key_resp.json); "
               "PUBLIC_KEY=$(jq -r '.public_key // \"N/A\"' "
               "/tmp/unsandbox_key_resp.json); "
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           IF WS-EXTEND-FLAG = "true"
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "xdg-open '"
                   FUNCTION TRIM(WS-PORTAL-BASE)
                   "/keys/extend?pk='\"$PUBLIC_KEY\" 2>/dev/null; "
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           ELSE
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "if [ \"$EXPIRED\" = \"true\" ]; then "
                   "echo -e '\x1b[31mExpired\x1b[0m'; "
                   "echo 'Public Key: '$PUBLIC_KEY; "
                   "echo 'Tier: '$(jq -r '.tier // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo 'Expired: '$(jq -r '.expires_at // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo -e '\x1b[33mTo renew: Visit "
                   "https://unsandbox.com/keys/extend\x1b[0m'; "
                   "rm -f /tmp/unsandbox_key_resp.json; "
                   "exit 1; "
                   "else "
                   "echo -e '\x1b[32mValid\x1b[0m'; "
                   "echo 'Public Key: '$PUBLIC_KEY; "
                   "echo 'Tier: '$(jq -r '.tier // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo 'Status: '$(jq -r '.status // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo 'Expires: '$(jq -r '.expires_at // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo 'Time Remaining: '$(jq -r "
                   "'.time_remaining // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo 'Rate Limit: '$(jq -r '.rate_limit // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo 'Burst: '$(jq -r '.burst // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "echo 'Concurrency: '$(jq -r '.concurrency // \"N/A\"' "
                   "/tmp/unsandbox_key_resp.json); "
                   "fi; "
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           STRING FUNCTION TRIM(WS-CURL-CMD)
               "rm -f /tmp/unsandbox_key_resp.json"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-SERVICE-RESIZE-ARGS.
      * Parse -v argument for vcpu
           MOVE 0 TO WS-VCPU.
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "-v"
                   ACCEPT WS-VCPU-STR FROM ARGUMENT-VALUE
                   MOVE FUNCTION NUMVAL(WS-VCPU-STR) TO WS-VCPU
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       SERVICE-RESIZE.
      * Validate vcpu
           IF WS-VCPU < 1 OR WS-VCPU > 8
               DISPLAY "Error: --resize requires -v N (1-8)"
                   UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Calculate RAM
           COMPUTE WS-RAM = WS-VCPU * 2.

      * Build and execute resize request with HMAC auth
           STRING "TS=$(date +%s); "
               "BODY='{\"vcpu\":" WS-VCPU "}'; "
               "SIG=$(echo -n \"$TS:PATCH:/services/"
               FUNCTION TRIM(WS-ID)
               ":$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X PATCH 'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-PUBLIC-KEY) "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" >/dev/null && "
               "echo -e '\x1b[32mService resized to " WS-VCPU
               " vCPU, " WS-RAM " GB RAM\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-SERVICE-UOD-ARGS.
      * Parse --enabled argument for unfreeze_on_demand
           MOVE SPACES TO WS-UOD-ENABLED.
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "--enabled"
                   ACCEPT WS-UOD-ENABLED FROM ARGUMENT-VALUE
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       SERVICE-SET-UNFREEZE-ON-DEMAND.
      * Validate enabled value
           IF WS-UOD-ENABLED NOT = "true" AND WS-UOD-ENABLED NOT = "false"
               DISPLAY "Error: --set-unfreeze-on-demand requires "
                   "--enabled true|false" UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Build and execute set unfreeze_on_demand request with HMAC auth
           STRING "TS=$(date +%s); "
               "BODY='{\"unfreeze_on_demand\":"
               FUNCTION TRIM(WS-UOD-ENABLED) "}'; "
               "SIG=$(echo -n \"$TS:PATCH:/services/"
               FUNCTION TRIM(WS-ID)
               ":$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X PATCH 'https://api.unsandbox.com/services/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer " FUNCTION TRIM(WS-PUBLIC-KEY) "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" >/dev/null && "
               "echo -e '\x1b[32mService unfreeze_on_demand set to "
               FUNCTION TRIM(WS-UOD-ENABLED) "\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       HANDLE-LANGUAGES.
      * Get API keys
           ACCEPT WS-PUBLIC-KEY FROM ENVIRONMENT "UNSANDBOX_PUBLIC_KEY".
           IF WS-PUBLIC-KEY NOT = SPACES
               ACCEPT WS-SECRET-KEY FROM ENVIRONMENT "UNSANDBOX_SECRET_KEY"
               IF WS-SECRET-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_SECRET_KEY not set"
                       UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
           ELSE
               ACCEPT WS-API-KEY FROM ENVIRONMENT "UNSANDBOX_API_KEY"
               IF WS-API-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_PUBLIC_KEY/SECRET_KEY or "
                       "UNSANDBOX_API_KEY not set" UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
               MOVE WS-API-KEY TO WS-PUBLIC-KEY
               MOVE WS-API-KEY TO WS-SECRET-KEY
           END-IF.

      * Parse --json flag
           MOVE SPACES TO WS-JSON-OUTPUT.
           ACCEPT WS-ARG2 FROM ARGUMENT-VALUE.
           IF WS-ARG2 = "--json"
               MOVE "true" TO WS-JSON-OUTPUT
           END-IF.

      * Perform languages list
           PERFORM LANGUAGES-LIST.

       LANGUAGES-LIST.
      * Languages list with 1-hour cache
           IF WS-JSON-OUTPUT = "true"
      * JSON output: extract language names as array with caching
               STRING "CACHE_TTL=3600; "
                   "CACHE_FILE=\"$HOME/.unsandbox/languages.json\"; "
                   "if [ -f \"$CACHE_FILE\" ]; then "
                   "CACHE_TS=$(jq -r '.timestamp // 0' \"$CACHE_FILE\" 2>/dev/null); "
                   "CURRENT_TS=$(date +%s); "
                   "AGE=$((CURRENT_TS - CACHE_TS)); "
                   "if [ $AGE -lt $CACHE_TTL ]; then "
                   "jq -c '.languages' \"$CACHE_FILE\"; exit 0; fi; fi; "
                   "TS=$(date +%s); "
                   "SIG=$(echo -n \"$TS:GET:/languages:\" | "
                   "openssl dgst -sha256 -hmac '"
                   FUNCTION TRIM(WS-SECRET-KEY)
                   "' | cut -d' ' -f2); "
                   "RESP=$(curl -s -X GET 'https://api.unsandbox.com/languages' "
                   "-H 'Authorization: Bearer "
                   FUNCTION TRIM(WS-PUBLIC-KEY)
                   "' "
                   "-H 'X-Timestamp: '$TS "
                   "-H 'X-Signature: '$SIG); "
                   "LANGS=$(echo \"$RESP\" | jq -c '[.languages[].name]'); "
                   "mkdir -p \"$HOME/.unsandbox\"; "
                   "echo \"{\\\"languages\\\":$LANGS,\\\"timestamp\\\":$(date +%s)}\" "
                   "> \"$CACHE_FILE\"; "
                   "echo \"$LANGS\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           ELSE
      * Plain output: one language per line with caching
               STRING "CACHE_TTL=3600; "
                   "CACHE_FILE=\"$HOME/.unsandbox/languages.json\"; "
                   "if [ -f \"$CACHE_FILE\" ]; then "
                   "CACHE_TS=$(jq -r '.timestamp // 0' \"$CACHE_FILE\" 2>/dev/null); "
                   "CURRENT_TS=$(date +%s); "
                   "AGE=$((CURRENT_TS - CACHE_TS)); "
                   "if [ $AGE -lt $CACHE_TTL ]; then "
                   "jq -r '.languages[]' \"$CACHE_FILE\"; exit 0; fi; fi; "
                   "TS=$(date +%s); "
                   "SIG=$(echo -n \"$TS:GET:/languages:\" | "
                   "openssl dgst -sha256 -hmac '"
                   FUNCTION TRIM(WS-SECRET-KEY)
                   "' | cut -d' ' -f2); "
                   "RESP=$(curl -s -X GET 'https://api.unsandbox.com/languages' "
                   "-H 'Authorization: Bearer "
                   FUNCTION TRIM(WS-PUBLIC-KEY)
                   "' "
                   "-H 'X-Timestamp: '$TS "
                   "-H 'X-Signature: '$SIG); "
                   "LANGS=$(echo \"$RESP\" | jq -c '[.languages[].name]'); "
                   "mkdir -p \"$HOME/.unsandbox\"; "
                   "echo \"{\\\"languages\\\":$LANGS,\\\"timestamp\\\":$(date +%s)}\" "
                   "> \"$CACHE_FILE\"; "
                   "echo \"$RESP\" | jq -r '.languages[].name'"
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           CALL "SYSTEM" USING WS-CURL-CMD.

       HANDLE-IMAGE.
      * Get API keys (try new format first, fall back to old)
           ACCEPT WS-PUBLIC-KEY FROM ENVIRONMENT "UNSANDBOX_PUBLIC_KEY".
           IF WS-PUBLIC-KEY NOT = SPACES
               ACCEPT WS-SECRET-KEY FROM ENVIRONMENT "UNSANDBOX_SECRET_KEY"
               IF WS-SECRET-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_SECRET_KEY not set"
                       UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
           ELSE
               ACCEPT WS-API-KEY FROM ENVIRONMENT "UNSANDBOX_API_KEY"
               IF WS-API-KEY = SPACES
                   DISPLAY "Error: UNSANDBOX_PUBLIC_KEY/SECRET_KEY or "
                       "UNSANDBOX_API_KEY not set" UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
               END-IF
               MOVE WS-API-KEY TO WS-PUBLIC-KEY
               MOVE WS-API-KEY TO WS-SECRET-KEY
           END-IF.

      * Initialize image parameters
           MOVE SPACES TO WS-ID.
           MOVE SPACES TO WS-NAME.
           MOVE SPACES TO WS-PORTS.
           MOVE SPACES TO WS-IMAGE-SOURCE-TYPE.
           MOVE SPACES TO WS-IMAGE-VISIBILITY.

      * Parse image arguments
           ACCEPT WS-ARG2 FROM ARGUMENT-VALUE.

           IF WS-ARG2 = "-l" OR WS-ARG2 = "--list"
               PERFORM IMAGE-LIST
           ELSE IF WS-ARG2 = "--info"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM IMAGE-INFO
           ELSE IF WS-ARG2 = "--delete"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM IMAGE-DELETE
           ELSE IF WS-ARG2 = "--lock"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM IMAGE-LOCK
           ELSE IF WS-ARG2 = "--unlock"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM IMAGE-UNLOCK
           ELSE IF WS-ARG2 = "--publish"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM PARSE-IMAGE-PUBLISH-ARGS
               PERFORM IMAGE-PUBLISH
           ELSE IF WS-ARG2 = "--visibility"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               ACCEPT WS-IMAGE-VISIBILITY FROM ARGUMENT-VALUE
               PERFORM IMAGE-VISIBILITY
           ELSE IF WS-ARG2 = "--spawn"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM PARSE-IMAGE-SPAWN-ARGS
               PERFORM IMAGE-SPAWN
           ELSE IF WS-ARG2 = "--clone"
               ACCEPT WS-ID FROM ARGUMENT-VALUE
               PERFORM PARSE-IMAGE-CLONE-ARGS
               PERFORM IMAGE-CLONE
           ELSE
               DISPLAY "Error: Use --list, --info, --delete, "
                   "--lock, --unlock, --publish, --visibility, "
                   "--spawn, or --clone" UPON SYSERR
               MOVE 1 TO RETURN-CODE
           END-IF.

       IMAGE-LIST.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:GET:/images:\" | "
               "openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X GET 'https://api.unsandbox.com/images' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG | jq ."
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       IMAGE-INFO.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:GET:/images/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X GET 'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG | jq ."
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       IMAGE-DELETE.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:DELETE:/images/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP=$(curl -s -w '\\n%{http_code}' -X DELETE "
               "'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG); "
               "HTTP_CODE=$(echo \"$RESP\" | tail -n1); "
               "BODY=$(echo \"$RESP\" | sed '$d'); "
               "if [ \"$HTTP_CODE\" = \"428\" ]; then "
               "CHALLENGE_ID=$(echo \"$BODY\" | jq -r '.challenge_id // empty'); "
               "echo -e '\\x1b[33mConfirmation required. Check your email "
               "for a one-time code.\\x1b[0m' >&2; "
               "echo -n 'Enter OTP: ' >&2; read OTP; "
               "if [ -z \"$OTP\" ]; then "
               "echo -e '\\x1b[31mError: Operation cancelled\\x1b[0m' >&2; "
               "exit 1; fi; "
               "TS2=$(date +%s); "
               "SIG2=$(echo -n \"$TS2:DELETE:/images/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP2=$(curl -s -w '\\n%{http_code}' -X DELETE "
               "'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS2 "
               "-H 'X-Signature: '$SIG2 "
               "-H 'X-Sudo-OTP: '$OTP "
               "-H 'X-Sudo-Challenge: '$CHALLENGE_ID); "
               "HTTP_CODE2=$(echo \"$RESP2\" | tail -n1); "
               "if [ \"$HTTP_CODE2\" = \"200\" ] || "
               "[ \"$HTTP_CODE2\" = \"204\" ]; then "
               "echo -e '\\x1b[32mImage deleted: "
               FUNCTION TRIM(WS-ID) "\\x1b[0m'; "
               "else echo \"$RESP2\" | sed '$d' | jq . 2>/dev/null || "
               "echo \"$RESP2\" | sed '$d'; exit 1; fi; "
               "elif [ \"$HTTP_CODE\" = \"200\" ] || "
               "[ \"$HTTP_CODE\" = \"204\" ]; then "
               "echo -e '\\x1b[32mImage deleted: "
               FUNCTION TRIM(WS-ID) "\\x1b[0m'; "
               "else echo \"$BODY\" | jq . 2>/dev/null || "
               "echo \"$BODY\"; exit 1; fi"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       IMAGE-LOCK.
           STRING "TS=$(date +%s); "
               "BODY='{}'; "
               "SIG=$(echo -n \"$TS:POST:/images/"
               FUNCTION TRIM(WS-ID)
               "/lock:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "/lock' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" >/dev/null && "
               "echo -e '\x1b[32mImage locked: "
               FUNCTION TRIM(WS-ID) "\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       IMAGE-UNLOCK.
           STRING "TS=$(date +%s); "
               "BODY='{}'; "
               "SIG=$(echo -n \"$TS:POST:/images/"
               FUNCTION TRIM(WS-ID)
               "/unlock:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP=$(curl -s -w '\\n%{http_code}' -X POST "
               "'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "/unlock' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\"); "
               "HTTP_CODE=$(echo \"$RESP\" | tail -n1); "
               "RESP_BODY=$(echo \"$RESP\" | sed '$d'); "
               "if [ \"$HTTP_CODE\" = \"428\" ]; then "
               "CHALLENGE_ID=$(echo \"$RESP_BODY\" | jq -r '.challenge_id // empty'); "
               "echo -e '\\x1b[33mConfirmation required. Check your email "
               "for a one-time code.\\x1b[0m' >&2; "
               "echo -n 'Enter OTP: ' >&2; read OTP; "
               "if [ -z \"$OTP\" ]; then "
               "echo -e '\\x1b[31mError: Operation cancelled\\x1b[0m' >&2; "
               "exit 1; fi; "
               "TS2=$(date +%s); "
               "SIG2=$(echo -n \"$TS2:POST:/images/"
               FUNCTION TRIM(WS-ID)
               "/unlock:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP2=$(curl -s -w '\\n%{http_code}' -X POST "
               "'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "/unlock' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS2 "
               "-H 'X-Signature: '$SIG2 "
               "-H 'X-Sudo-OTP: '$OTP "
               "-H 'X-Sudo-Challenge: '$CHALLENGE_ID "
               "-d \"$BODY\"); "
               "HTTP_CODE2=$(echo \"$RESP2\" | tail -n1); "
               "if [ \"$HTTP_CODE2\" = \"200\" ] || "
               "[ \"$HTTP_CODE2\" = \"204\" ]; then "
               "echo -e '\\x1b[32mImage unlocked: "
               FUNCTION TRIM(WS-ID) "\\x1b[0m'; "
               "else echo \"$RESP2\" | sed '$d' | jq . 2>/dev/null || "
               "echo \"$RESP2\" | sed '$d'; exit 1; fi; "
               "elif [ \"$HTTP_CODE\" = \"200\" ] || "
               "[ \"$HTTP_CODE\" = \"204\" ]; then "
               "echo -e '\\x1b[32mImage unlocked: "
               FUNCTION TRIM(WS-ID) "\\x1b[0m'; "
               "else echo \"$RESP_BODY\" | jq . 2>/dev/null || "
               "echo \"$RESP_BODY\"; exit 1; fi"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-IMAGE-PUBLISH-ARGS.
      * Parse --source-type and --name for publish
           MOVE SPACES TO WS-IMAGE-SOURCE-TYPE.
           MOVE SPACES TO WS-NAME.
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "--source-type"
                   ACCEPT WS-IMAGE-SOURCE-TYPE FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--name"
                   ACCEPT WS-NAME FROM ARGUMENT-VALUE
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       IMAGE-PUBLISH.
      * Validate source-type
           IF WS-IMAGE-SOURCE-TYPE = SPACES
               DISPLAY "Error: --publish requires --source-type "
                   "(service or snapshot)" UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Build publish request
           STRING "TS=$(date +%s); "
               "BODY='{\"source_type\":\""
               FUNCTION TRIM(WS-IMAGE-SOURCE-TYPE)
               "\",\"source_id\":\""
               FUNCTION TRIM(WS-ID) "\""
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           IF WS-NAME NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"name\":\"" FUNCTION TRIM(WS-NAME) "\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           STRING FUNCTION TRIM(WS-CURL-CMD)
               "}'; "
               "SIG=$(echo -n \"$TS:POST:/images/publish:$BODY\" | "
               "openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/images/publish' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" && "
               "echo -e '\x1b[32mImage published\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       IMAGE-VISIBILITY.
           STRING "TS=$(date +%s); "
               "BODY='{\"visibility\":\""
               FUNCTION TRIM(WS-IMAGE-VISIBILITY)
               "\"}'; "
               "SIG=$(echo -n \"$TS:POST:/images/"
               FUNCTION TRIM(WS-ID)
               "/visibility:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "/visibility' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" >/dev/null && "
               "echo -e '\x1b[32mImage visibility set to: "
               FUNCTION TRIM(WS-IMAGE-VISIBILITY) "\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-IMAGE-SPAWN-ARGS.
      * Parse --name and --ports for spawn
           MOVE SPACES TO WS-NAME.
           MOVE SPACES TO WS-PORTS.
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "--name"
                   ACCEPT WS-NAME FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--ports"
                   ACCEPT WS-PORTS FROM ARGUMENT-VALUE
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       IMAGE-SPAWN.
      * Build spawn request
           STRING "TS=$(date +%s); "
               "BODY='{"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           IF WS-NAME NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "\"name\":\"" FUNCTION TRIM(WS-NAME) "\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           IF WS-PORTS NOT = SPACES
               IF WS-NAME NOT = SPACES
                   STRING FUNCTION TRIM(WS-CURL-CMD) ","
                       DELIMITED BY SIZE INTO WS-CURL-CMD
                   END-STRING
               END-IF
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "\"ports\":[" FUNCTION TRIM(WS-PORTS) "]"
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           STRING FUNCTION TRIM(WS-CURL-CMD)
               "}'; "
               "SIG=$(echo -n \"$TS:POST:/images/"
               FUNCTION TRIM(WS-ID)
               "/spawn:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "/spawn' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" && "
               "echo -e '\x1b[32mService spawned from image\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-IMAGE-CLONE-ARGS.
      * Parse --name for clone
           MOVE SPACES TO WS-NAME.
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "--name"
                   ACCEPT WS-NAME FROM ARGUMENT-VALUE
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

       IMAGE-CLONE.
      * Build clone request
           STRING "TS=$(date +%s); "
               "BODY='{"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           IF WS-NAME NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   "\"name\":\"" FUNCTION TRIM(WS-NAME) "\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           STRING FUNCTION TRIM(WS-CURL-CMD)
               "}'; "
               "SIG=$(echo -n \"$TS:POST:/images/"
               FUNCTION TRIM(WS-ID)
               "/clone:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/images/"
               FUNCTION TRIM(WS-ID)
               "/clone' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" && "
               "echo -e '\x1b[32mImage cloned\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       HANDLE-SNAPSHOT.
      * Get credentials
           ACCEPT WS-PUBLIC-KEY FROM ENVIRONMENT
               "UNSANDBOX_PUBLIC_KEY".
           ACCEPT WS-SECRET-KEY FROM ENVIRONMENT
               "UNSANDBOX_SECRET_KEY".
           IF WS-PUBLIC-KEY = SPACES OR WS-SECRET-KEY = SPACES
               DISPLAY "Error: API keys not set" UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

      * Get second argument (operation or --list)
           ACCEPT WS-ARG2 FROM ARGUMENT-VALUE.

           EVALUATE WS-ARG2
               WHEN "--list"
               WHEN "-l"
                   PERFORM SNAPSHOT-LIST
               WHEN "--info"
                   ACCEPT WS-ID FROM ARGUMENT-VALUE
                   PERFORM SNAPSHOT-INFO
               WHEN "--delete"
                   ACCEPT WS-ID FROM ARGUMENT-VALUE
                   PERFORM SNAPSHOT-DELETE
               WHEN "--lock"
                   ACCEPT WS-ID FROM ARGUMENT-VALUE
                   PERFORM SNAPSHOT-LOCK
               WHEN "--unlock"
                   ACCEPT WS-ID FROM ARGUMENT-VALUE
                   PERFORM SNAPSHOT-UNLOCK
               WHEN "--restore"
                   ACCEPT WS-ID FROM ARGUMENT-VALUE
                   PERFORM SNAPSHOT-RESTORE
               WHEN "--clone"
                   ACCEPT WS-ID FROM ARGUMENT-VALUE
                   PERFORM PARSE-SNAPSHOT-CLONE-ARGS
                   PERFORM SNAPSHOT-CLONE
               WHEN OTHER
                   DISPLAY "Usage: un snapshot [options]" UPON SYSERR
                   DISPLAY "  --list, -l       List snapshots" UPON SYSERR
                   DISPLAY "  --info ID        Get snapshot details"
                       UPON SYSERR
                   DISPLAY "  --delete ID      Delete snapshot"
                       UPON SYSERR
                   DISPLAY "  --lock ID        Lock snapshot" UPON SYSERR
                   DISPLAY "  --unlock ID      Unlock snapshot" UPON SYSERR
                   DISPLAY "  --restore ID     Restore snapshot"
                       UPON SYSERR
                   DISPLAY "  --clone ID       Clone snapshot" UPON SYSERR
                   MOVE 1 TO RETURN-CODE
                   STOP RUN
           END-EVALUATE.

       SNAPSHOT-LIST.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:GET:/snapshots:\" | "
               "openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X GET 'https://api.unsandbox.com/snapshots' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG | jq ."
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SNAPSHOT-INFO.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:GET:/snapshots/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X GET 'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG | jq ."
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SNAPSHOT-DELETE.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:DELETE:/snapshots/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP=$(curl -s -w '\n%{http_code}' -X DELETE "
               "'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG); "
               "HTTP_CODE=$(echo \"$RESP\" | tail -1); "
               "BODY=$(echo \"$RESP\" | head -n -1); "
               "if [ \"$HTTP_CODE\" = \"428\" ]; then "
               "OTP=$(echo \"$BODY\" | jq -r '.otp // empty'); "
               "if [ -n \"$OTP\" ]; then "
               "TS2=$(date +%s); "
               "SIG2=$(echo -n \"$TS2:DELETE:/snapshots/"
               FUNCTION TRIM(WS-ID)
               ":\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X DELETE 'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS2 "
               "-H 'X-Signature: '$SIG2 "
               "-H 'X-Sudo-OTP: '$OTP | jq .; "
               "echo -e '\x1b[32mSnapshot deleted\x1b[0m'; fi; "
               "else echo \"$BODY\" | jq .; fi"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SNAPSHOT-LOCK.
           STRING "TS=$(date +%s); "
               "SIG=$(echo -n \"$TS:POST:/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/lock:\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/lock' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG | jq . && "
               "echo -e '\x1b[32mSnapshot locked\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SNAPSHOT-UNLOCK.
           STRING "TS=$(date +%s); "
               "BODY='{}'; "
               "SIG=$(echo -n \"$TS:POST:/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/unlock:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "RESP=$(curl -s -w '\n%{http_code}' -X POST "
               "'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/unlock' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\"); "
               "HTTP_CODE=$(echo \"$RESP\" | tail -1); "
               "BODY_RESP=$(echo \"$RESP\" | head -n -1); "
               "if [ \"$HTTP_CODE\" = \"428\" ]; then "
               "OTP=$(echo \"$BODY_RESP\" | jq -r '.otp // empty'); "
               "if [ -n \"$OTP\" ]; then "
               "TS2=$(date +%s); "
               "SIG2=$(echo -n \"$TS2:POST:/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/unlock:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/unlock' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS2 "
               "-H 'X-Signature: '$SIG2 "
               "-H 'X-Sudo-OTP: '$OTP "
               "-d \"$BODY\" | jq .; "
               "echo -e '\x1b[32mSnapshot unlocked\x1b[0m'; fi; "
               "else echo \"$BODY_RESP\" | jq .; fi"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       SNAPSHOT-RESTORE.
           STRING "TS=$(date +%s); "
               "BODY='{}'; "
               "SIG=$(echo -n \"$TS:POST:/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/restore:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/restore' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" | jq . && "
               "echo -e '\x1b[32mSnapshot restored\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.

       PARSE-SNAPSHOT-CLONE-ARGS.
      * Parse --type, --name, --ports, --shell
           MOVE SPACES TO WS-TYPE.
           MOVE SPACES TO WS-NAME.
           MOVE SPACES TO WS-PORTS.
           MOVE SPACES TO WS-SHELL.
           ACCEPT WS-ARG3 FROM ARGUMENT-VALUE.
           PERFORM UNTIL WS-ARG3 = SPACES
               IF WS-ARG3 = "--type"
                   ACCEPT WS-TYPE FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--name"
                   ACCEPT WS-NAME FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--ports"
                   ACCEPT WS-PORTS FROM ARGUMENT-VALUE
               ELSE IF WS-ARG3 = "--shell"
                   ACCEPT WS-SHELL FROM ARGUMENT-VALUE
               END-IF
               ACCEPT WS-ARG3 FROM ARGUMENT-VALUE
           END-PERFORM.

           IF WS-TYPE = SPACES
               DISPLAY "Error: --type required (session or service)"
                   UPON SYSERR
               MOVE 1 TO RETURN-CODE
               STOP RUN
           END-IF.

       SNAPSHOT-CLONE.
      * Build clone request
           STRING "TS=$(date +%s); "
               "BODY='{\"type\":\"" FUNCTION TRIM(WS-TYPE) "\""
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           IF WS-NAME NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"name\":\"" FUNCTION TRIM(WS-NAME) "\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           IF WS-PORTS NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"ports\":[" FUNCTION TRIM(WS-PORTS) "]"
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           IF WS-SHELL NOT = SPACES
               STRING FUNCTION TRIM(WS-CURL-CMD)
                   ",\"shell\":\"" FUNCTION TRIM(WS-SHELL) "\""
                   DELIMITED BY SIZE INTO WS-CURL-CMD
               END-STRING
           END-IF.

           STRING FUNCTION TRIM(WS-CURL-CMD)
               "}'; "
               "SIG=$(echo -n \"$TS:POST:/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/clone:$BODY\" | openssl dgst -sha256 -hmac '"
               FUNCTION TRIM(WS-SECRET-KEY)
               "' | cut -d' ' -f2); "
               "curl -s -X POST 'https://api.unsandbox.com/snapshots/"
               FUNCTION TRIM(WS-ID)
               "/clone' "
               "-H 'Content-Type: application/json' "
               "-H 'Authorization: Bearer "
               FUNCTION TRIM(WS-PUBLIC-KEY)
               "' "
               "-H 'X-Timestamp: '$TS "
               "-H 'X-Signature: '$SIG "
               "-d \"$BODY\" | jq . && "
               "echo -e '\x1b[32mSnapshot cloned\x1b[0m'"
               DELIMITED BY SIZE INTO WS-CURL-CMD
           END-STRING.

           CALL "SYSTEM" USING WS-CURL-CMD.
