diff --git a/essential/visible/service/helper/cipher/cipher.go b/essential/visible/service/helper/cipher/cipher.go index e69de29..5a0da83 100644 --- a/essential/visible/service/helper/cipher/cipher.go +++ b/essential/visible/service/helper/cipher/cipher.go @@ -0,0 +1,447 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Cipher +| +| Purpose: +| - Provide reusable AES-256 encryption and decryption utilities for +| standard and salted file-based cryptographic workflows. +| +| Guideline: +| - Use only AES-256 compatible keys. +| - Use encrypt-standard for non-salted encryption workflows. +| - Use encrypt-salted for self-contained encrypted file workflows. +| - Use decrypt-standard for non-salted encrypted files. +| - Use decrypt-salted for self-contained encrypted files. +| - Always provide valid input and output file paths. +| +| Example: +| - ObrimCipher("encrypt-standard", config) +| - ObrimCipher("encrypt-salted", config) +| - ObrimCipher("decrypt-standard", config) +| - ObrimCipher("decrypt-salted", config) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package cipher + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" + "encoding/json" + "errors" + "io" + "os" + "path/filepath" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/retriever" + "go/module/essential/visible/service/helper/status" +) + +const ( + obrimCipherAlgorithm = "AES-256" + obrimCipherSignature = "OBRIMCIPHER" + obrimCipherVersion = "1" + obrimCipherSaltSize = 32 + obrimCipherNonceSize = 12 +) + +type obrimCipherResponse struct { + Status bool `json:"status"` + Code string `json:"code"` + Payload any `json:"payload"` +} + +// ObrimCipher executes encryption and decryption workflows. +func ObrimCipher(operationType string, config map[string]any) map[string]any { + _, _ = retriever.ObrimRetriever, status.ObrimStatus + + log.ObrimLog("INIT", "Cipher operation initialized.") + + if err := obrimCipherValidateType(operationType); err != nil { + return obrimCipherBuildResponse(false, "FAILED_INVALID_TYPE", nil) + } + + if err := obrimCipherValidateConfig(config); err != nil { + return obrimCipherBuildResponse(false, "FAILED_INVALID_CONFIG", nil) + } + + keyValue := config["key"].(string) + + if err := obrimCipherValidateKey(keyValue); err != nil { + return obrimCipherBuildResponse(false, "FAILED_INVALID_KEY", nil) + } + + inputPath, err := obrimCipherResolvePath(config["input"].(string)) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_INPUT_PATH_VALIDATION", nil) + } + + outputPath, err := obrimCipherResolvePath(config["output"].(string)) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_OUTPUT_PATH_VALIDATION", nil) + } + + inputData, err := obrimCipherReadInput(inputPath) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_SOURCE_ACCESS", nil) + } + + switch operationType { + case "encrypt-standard": + encryptedData, err := obrimCipherEncryptStandard([]byte(keyValue), inputData) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_ENCRYPTION", nil) + } + + if err := obrimCipherWriteOutput(outputPath, encryptedData); err != nil { + return obrimCipherBuildResponse(false, "FAILED_OUTPUT_WRITE", nil) + } + + return obrimCipherBuildResponse(true, "SUCCESS_ENCRYPT_STANDARD", map[string]any{ + "operation": operationType, + "algorithm": obrimCipherAlgorithm, + "inputPath": inputPath, + "outputPath": outputPath, + }) + + case "encrypt-salted": + salt, err := obrimCipherGenerateSalt() + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_SALT_GENERATION", nil) + } + + encryptedData, err := obrimCipherEncryptSalted([]byte(keyValue), salt, inputData) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_ENCRYPTION", nil) + } + + if err := obrimCipherWriteOutput(outputPath, encryptedData); err != nil { + return obrimCipherBuildResponse(false, "FAILED_OUTPUT_WRITE", nil) + } + + return obrimCipherBuildResponse(true, "SUCCESS_ENCRYPT_SALTED", map[string]any{ + "operation": operationType, + "algorithm": obrimCipherAlgorithm, + "format": obrimCipherSignature, + "version": obrimCipherVersion, + "inputPath": inputPath, + "outputPath": outputPath, + }) + + case "decrypt-standard": + decryptedData, err := obrimCipherDecryptStandard([]byte(keyValue), inputData) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_DECRYPTION", nil) + } + + if err := obrimCipherWriteOutput(outputPath, decryptedData); err != nil { + return obrimCipherBuildResponse(false, "FAILED_OUTPUT_WRITE", nil) + } + + return obrimCipherBuildResponse(true, "SUCCESS_DECRYPT_STANDARD", map[string]any{ + "operation": operationType, + "algorithm": obrimCipherAlgorithm, + "inputPath": inputPath, + "outputPath": outputPath, + }) + + case "decrypt-salted": + signature, version, err := obrimCipherParseHeader(inputData) + if err != nil { + if err.Error() == "version" { + return obrimCipherBuildResponse(false, "FAILED_VERSION_VALIDATION", nil) + } + + return obrimCipherBuildResponse(false, "FAILED_SIGNATURE_VALIDATION", nil) + } + + salt, err := obrimCipherExtractSalt(inputData) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_SALT_EXTRACTION", nil) + } + + payload, err := obrimCipherExtractPayload(inputData) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_PAYLOAD_EXTRACTION", nil) + } + + decryptedData, err := obrimCipherDecryptSalted([]byte(keyValue), salt, payload) + if err != nil { + return obrimCipherBuildResponse(false, "FAILED_DECRYPTION", nil) + } + + if err := obrimCipherWriteOutput(outputPath, decryptedData); err != nil { + return obrimCipherBuildResponse(false, "FAILED_OUTPUT_WRITE", nil) + } + + return obrimCipherBuildResponse(true, "SUCCESS_DECRYPT_SALTED", map[string]any{ + "operation": operationType, + "algorithm": obrimCipherAlgorithm, + "format": signature, + "version": version, + "inputPath": inputPath, + "outputPath": outputPath, + }) + } + + return obrimCipherBuildResponse(false, "FAILED_UNKNOWN_OPERATION", nil) +} + +// obrimCipherValidateType validates operation type. +func obrimCipherValidateType(operationType string) error { + switch operationType { + case "encrypt-standard", "encrypt-salted", "decrypt-standard", "decrypt-salted": + return nil + default: + return errors.New("invalid") + } +} + +// obrimCipherValidateConfig validates configuration. +func obrimCipherValidateConfig(config map[string]any) error { + if config == nil { + return errors.New("invalid") + } + + keyValue, keyExists := config["key"].(string) + inputValue, inputExists := config["input"].(string) + outputValue, outputExists := config["output"].(string) + + if !keyExists || !inputExists || !outputExists { + return errors.New("invalid") + } + + if keyValue == "" || inputValue == "" || outputValue == "" { + return errors.New("invalid") + } + + return nil +} + +// obrimCipherValidateKey validates AES-256 key requirements. +func obrimCipherValidateKey(key []byte) error { + if len(key) != 32 { + return errors.New("invalid") + } + + return nil +} + +// obrimCipherResolvePath resolves path to absolute path. +func obrimCipherResolvePath(path string) (string, error) { + return filepath.Abs(path) +} + +// obrimCipherReadInput reads source file content. +func obrimCipherReadInput(path string) ([]byte, error) { + fileInfo, err := os.Stat(path) + if err != nil { + return nil, err + } + + if fileInfo.IsDir() { + return nil, errors.New("directory") + } + + return os.ReadFile(path) +} + +// obrimCipherWriteOutput writes processed content. +func obrimCipherWriteOutput(path string, data []byte) error { + directory := filepath.Dir(path) + + if err := os.MkdirAll(directory, 0755); err != nil { + return err + } + + tempFile, err := os.CreateTemp(directory, "obrim-cipher-*") + if err != nil { + return err + } + + tempPath := tempFile.Name() + + if _, err := tempFile.Write(data); err != nil { + _ = tempFile.Close() + _ = os.Remove(tempPath) + return err + } + + if err := tempFile.Close(); err != nil { + _ = os.Remove(tempPath) + return err + } + + if err := os.Rename(tempPath, path); err != nil { + _ = os.Remove(tempPath) + return err + } + + return nil +} + +// obrimCipherBuildResponse builds standardized response. +func obrimCipherBuildResponse(statusValue bool, code string, payload any) map[string]any { + response := obrimCipherResponse{ + Status: statusValue, + Code: code, + Payload: payload, + } + + encoded, _ := json.Marshal(response) + + var result map[string]any + + _ = json.Unmarshal(encoded, &result) + + return result +} + +// obrimCipherEncryptStandard encrypts AES-256 data. +func obrimCipherEncryptStandard(key []byte, data []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + // Mutable variable: nonce buffer. + nonce := make([]byte, obrimCipherNonceSize) + + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return nil, err + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } + + ciphertext := gcm.Seal(nil, nonce, data, nil) + + return append(nonce, ciphertext...), nil +} + +// obrimCipherGenerateSalt generates cryptographic salt. +func obrimCipherGenerateSalt() ([]byte, error) { + // Mutable variable: salt buffer. + salt := make([]byte, obrimCipherSaltSize) + + if _, err := io.ReadFull(rand.Reader, salt); err != nil { + return nil, err + } + + return salt, nil +} + +// obrimCipherBuildHeader builds file header. +func obrimCipherBuildHeader() []byte { + return []byte(obrimCipherSignature + ":" + obrimCipherVersion + ":") +} + +// obrimCipherEncryptSalted encrypts AES-256 data with embedded salt. +func obrimCipherEncryptSalted(key []byte, salt []byte, data []byte) ([]byte, error) { + derivedKey := sha256.Sum256(append(key, salt...)) + + encryptedData, err := obrimCipherEncryptStandard(derivedKey[:], data) + if err != nil { + return nil, err + } + + header := obrimCipherBuildHeader() + + var buffer bytes.Buffer + + buffer.Write(header) + buffer.Write(salt) + buffer.Write(encryptedData) + + return buffer.Bytes(), nil +} + +// obrimCipherDecryptStandard decrypts AES-256 encrypted data. +func obrimCipherDecryptStandard(key []byte, data []byte) ([]byte, error) { + if len(data) <= obrimCipherNonceSize { + return nil, errors.New("invalid") + } + + nonce := data[:obrimCipherNonceSize] + payload := data[obrimCipherNonceSize:] + + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } + + return gcm.Open(nil, nonce, payload, nil) +} + +// obrimCipherParseHeader parses header metadata. +func obrimCipherParseHeader(data []byte) (string, string, error) { + header := obrimCipherBuildHeader() + + if len(data) < len(header)+obrimCipherSaltSize { + return "", "", errors.New("signature") + } + + if !bytes.HasPrefix(data, header) { + return "", "", errors.New("signature") + } + + return obrimCipherSignature, obrimCipherVersion, nil +} + +// obrimCipherExtractSalt extracts salt. +func obrimCipherExtractSalt(data []byte) ([]byte, error) { + headerLength := len(obrimCipherBuildHeader()) + + if len(data) < headerLength+obrimCipherSaltSize { + return nil, errors.New("invalid") + } + + return data[headerLength : headerLength+obrimCipherSaltSize], nil +} + +// obrimCipherExtractPayload extracts encrypted payload. +func obrimCipherExtractPayload(data []byte) ([]byte, error) { + headerLength := len(obrimCipherBuildHeader()) + offset := headerLength + obrimCipherSaltSize + + if len(data) <= offset { + return nil, errors.New("invalid") + } + + return data[offset:], nil +} + +// obrimCipherDecryptSalted decrypts AES-256 encrypted data using salt. +func obrimCipherDecryptSalted(key []byte, salt []byte, payload []byte) ([]byte, error) { + derivedKey := sha256.Sum256(append(key, salt...)) + + return obrimCipherDecryptStandard(derivedKey[:], payload) +} diff --git a/essential/visible/service/helper/codec/codec.go b/essential/visible/service/helper/codec/codec.go index e69de29..4940a2a 100644 --- a/essential/visible/service/helper/codec/codec.go +++ b/essential/visible/service/helper/codec/codec.go @@ -0,0 +1,527 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Codec +| +| Purpose: +| - Provide unified encoding and decoding capabilities using Base8, +| Base10, Base16, Base32, Base64, and Sqids with centralized +| validation, dispatching, transformation management, and +| structured result handling. +| +| Guideline: +| - Use ObrimCodec() as the public entry point. +| - Validate all parameters before dispatching operations. +| - Use supported formats only. +| - Handle all failures through structured responses. +| +| Example: +| - ObrimCodec("encode", config) +| - ObrimCodec("decode", config) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package codec + +import ( + "encoding/base32" + "encoding/base64" + "encoding/hex" + "errors" + "fmt" + "strconv" + "strings" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/retriever" + "go/module/essential/visible/service/helper/status" + + "github.com/sqids/sqids-go" +) + +// ObrimCodecResult represents the standardized utility response. +type ObrimCodecResult struct { + Status bool `json:"status"` + Code string `json:"code"` + Payload map[string]any `json:"payload"` +} + +// ObrimCodecConfig represents validated codec configuration. +type ObrimCodecConfig struct { + Format string + Data any + Charset string + Salt string + Case string + Length int +} + +// ObrimCodec validates configuration, dispatches codec operations, and returns structured results. +func ObrimCodec(operation string, config map[string]any) map[string]any { + _ = retriever.ObrimRetriever + status.ObrimStatus("INFO", "Codec operation initialized.") + log.ObrimLog("INIT", "Codec operation initialized.") + + validatedConfig, validationCode, validationError := obrimCodecValidation(operation, config) + if validationError != nil { + status.ObrimStatus("ERROR", validationError.Error()) + log.ObrimLog("ERROR", validationError.Error()) + + return map[string]any{ + "status": false, + "code": validationCode, + "payload": nil, + } + } + + payload, dispatchCode, dispatchError := obrimCodecDispatch(operation, validatedConfig) + if dispatchError != nil { + status.ObrimStatus("ERROR", dispatchError.Error()) + log.ObrimLog("ERROR", dispatchError.Error()) + + return map[string]any{ + "status": false, + "code": dispatchCode, + "payload": nil, + } + } + + status.ObrimStatus("SUCCESS", "Codec operation completed.") + log.ObrimLog("SUCCESS", "Codec operation completed.") + + return map[string]any{ + "status": true, + "code": dispatchCode, + "payload": payload, + } +} + +// obrimCodecValidation validates required parameters, supported operations, formats, and parameter types. +func obrimCodecValidation(operation string, config map[string]any) (ObrimCodecConfig, string, error) { + // Mutable validated configuration. + var validated ObrimCodecConfig + + switch operation { + case "encode", "decode": + default: + return validated, "FAILED_UNSUPPORTED_OPERATION", errors.New("unsupported operation") + } + + // Mutable format value. + formatValue, exists := config["format"] + if !exists { + return validated, "FAILED_MISSING_FORMAT", errors.New("missing format") + } + + format, ok := formatValue.(string) + if !ok { + return validated, "FAILED_INVALID_FORMAT_TYPE", errors.New("invalid format type") + } + + switch format { + case "base8", "base10", "base16", "base32", "base64", "sqids": + default: + return validated, "FAILED_UNSUPPORTED_FORMAT", errors.New("unsupported format") + } + + // Mutable data value. + dataValue, exists := config["data"] + if !exists { + return validated, "FAILED_MISSING_DATA", errors.New("missing data") + } + + switch dataValue.(type) { + case string, []byte: + default: + return validated, "FAILED_INVALID_DATA_TYPE", errors.New("invalid data type") + } + + // Mutable charset value. + charsetValue, exists := config["charset"] + if !exists { + return validated, "FAILED_MISSING_CHARSET", errors.New("missing charset") + } + + charset, ok := charsetValue.(string) + if !ok { + return validated, "FAILED_INVALID_CHARSET_TYPE", errors.New("invalid charset type") + } + + // Mutable salt value. + saltValue, exists := config["salt"] + if !exists { + return validated, "FAILED_MISSING_SALT", errors.New("missing salt") + } + + salt, ok := saltValue.(string) + if !ok { + return validated, "FAILED_INVALID_SALT_TYPE", errors.New("invalid salt type") + } + + validated.Format = format + validated.Data = dataValue + validated.Charset = charset + validated.Salt = salt + + if format == "sqids" { + // Mutable length value. + lengthValue, exists := config["length"] + if !exists { + return validated, "FAILED_MISSING_LENGTH", errors.New("missing length") + } + + switch value := lengthValue.(type) { + case int: + validated.Length = value + case int64: + validated.Length = int(value) + case float64: + validated.Length = int(value) + default: + return validated, "FAILED_INVALID_LENGTH_TYPE", errors.New("invalid length type") + } + } else { + // Mutable case value. + caseValue, exists := config["case"] + if !exists { + return validated, "FAILED_MISSING_CASE", errors.New("missing case") + } + + caseRule, ok := caseValue.(string) + if !ok { + return validated, "FAILED_INVALID_CASE_TYPE", errors.New("invalid case type") + } + + switch caseRule { + case "lower", "upper": + default: + return validated, "FAILED_INVALID_CASE_VALUE", errors.New("invalid case value") + } + + validated.Case = caseRule + } + + return validated, "SUCCESS_VALIDATION", nil +} + +// obrimCodecDispatch routes validated requests to the appropriate codec implementation. +func obrimCodecDispatch(operation string, config ObrimCodecConfig) (map[string]any, string, error) { + switch operation { + case "encode": + switch config.Format { + case "base8": + return obrimCodecEncodeBase8(config) + case "base10": + return obrimCodecEncodeBase10(config) + case "base16": + return obrimCodecEncodeBase16(config) + case "base32": + return obrimCodecEncodeBase32(config) + case "base64": + return obrimCodecEncodeBase64(config) + case "sqids": + return obrimCodecEncodeSqids(config) + } + case "decode": + switch config.Format { + case "base8": + return obrimCodecDecodeBase8(config) + case "base10": + return obrimCodecDecodeBase10(config) + case "base16": + return obrimCodecDecodeBase16(config) + case "base32": + return obrimCodecDecodeBase32(config) + case "base64": + return obrimCodecDecodeBase64(config) + case "sqids": + return obrimCodecDecodeSqids(config) + } + } + + return nil, "FAILED_DISPATCH", errors.New("dispatch failed") +} + +// obrimCodecEncodeBase8 encodes data using Base8 encoding. +func obrimCodecEncodeBase8(config ObrimCodecConfig) (map[string]any, string, error) { + value := obrimCodecBytesToBase(config, 8) + + return map[string]any{ + "operation": "encode", + "format": "base8", + "value": obrimCodecApplyCase(obrimCodecTransformEncode(value, config), config.Case), + }, "SUCCESS_BASE8_ENCODE", nil +} + +// obrimCodecEncodeBase10 encodes data using Base10 encoding. +func obrimCodecEncodeBase10(config ObrimCodecConfig) (map[string]any, string, error) { + value := obrimCodecBytesToBase(config, 10) + + return map[string]any{ + "operation": "encode", + "format": "base10", + "value": obrimCodecApplyCase(obrimCodecTransformEncode(value, config), config.Case), + }, "SUCCESS_BASE10_ENCODE", nil +} + +// obrimCodecEncodeBase16 encodes data using Base16 encoding. +func obrimCodecEncodeBase16(config ObrimCodecConfig) (map[string]any, string, error) { + value := hex.EncodeToString(obrimCodecBytes(config.Data)) + value = obrimCodecApplyCase(value, config.Case) + value = obrimCodecTransformEncode(value, config) + + return map[string]any{ + "operation": "encode", + "format": "base16", + "value": value, + }, "SUCCESS_BASE16_ENCODE", nil +} + +// obrimCodecEncodeBase32 encodes data using Base32 encoding. +func obrimCodecEncodeBase32(config ObrimCodecConfig) (map[string]any, string, error) { + value := base32.StdEncoding.EncodeToString(obrimCodecBytes(config.Data)) + value = obrimCodecApplyCase(value, config.Case) + value = obrimCodecTransformEncode(value, config) + + return map[string]any{ + "operation": "encode", + "format": "base32", + "value": value, + }, "SUCCESS_BASE32_ENCODE", nil +} + +// obrimCodecEncodeBase64 encodes data using Base64 encoding. +func obrimCodecEncodeBase64(config ObrimCodecConfig) (map[string]any, string, error) { + value := base64.StdEncoding.EncodeToString(obrimCodecBytes(config.Data)) + value = obrimCodecApplyCase(value, config.Case) + value = obrimCodecTransformEncode(value, config) + + return map[string]any{ + "operation": "encode", + "format": "base64", + "value": value, + }, "SUCCESS_BASE64_ENCODE", nil +} + +// obrimCodecEncodeSqids encodes data using Sqids encoding with minimum length enforcement. +func obrimCodecEncodeSqids(config ObrimCodecConfig) (map[string]any, string, error) { + options := sqids.Options{ + MinLength: uint8(config.Length), + Alphabet: obrimCodecAlphabet(config.Charset), + Blocklist: []string{}, + } + + instance, err := sqids.New(options) + if err != nil { + return nil, "FAILED_SQIDS_INITIALIZATION", err + } + + number, err := strconv.ParseUint(obrimCodecTransformNumberInput(config), 10, 64) + if err != nil { + return nil, "FAILED_SQIDS_INPUT", err + } + + value, err := instance.Encode([]uint64{number}) + if err != nil { + return nil, "FAILED_SQIDS_ENCODE", err + } + + value = config.Salt + value + + return map[string]any{ + "operation": "encode", + "format": "sqids", + "value": value, + }, "SUCCESS_SQIDS_ENCODE", nil +} + +// obrimCodecDecodeBase8 decodes Base8 encoded data. +func obrimCodecDecodeBase8(config ObrimCodecConfig) (map[string]any, string, error) { + value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) + + return map[string]any{ + "operation": "decode", + "format": "base8", + "value": value, + }, "SUCCESS_BASE8_DECODE", nil +} + +// obrimCodecDecodeBase10 decodes Base10 encoded data. +func obrimCodecDecodeBase10(config ObrimCodecConfig) (map[string]any, string, error) { + value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) + + return map[string]any{ + "operation": "decode", + "format": "base10", + "value": value, + }, "SUCCESS_BASE10_DECODE", nil +} + +// obrimCodecDecodeBase16 decodes Base16 encoded data. +func obrimCodecDecodeBase16(config ObrimCodecConfig) (map[string]any, string, error) { + value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) + + decoded, err := hex.DecodeString(value) + if err != nil { + return nil, "FAILED_BASE16_DECODE", err + } + + return map[string]any{ + "operation": "decode", + "format": "base16", + "value": string(decoded), + }, "SUCCESS_BASE16_DECODE", nil +} + +// obrimCodecDecodeBase32 decodes Base32 encoded data. +func obrimCodecDecodeBase32(config ObrimCodecConfig) (map[string]any, string, error) { + value := strings.ToUpper(obrimCodecTransformDecode(obrimCodecString(config.Data), config)) + + decoded, err := base32.StdEncoding.DecodeString(value) + if err != nil { + return nil, "FAILED_BASE32_DECODE", err + } + + return map[string]any{ + "operation": "decode", + "format": "base32", + "value": string(decoded), + }, "SUCCESS_BASE32_DECODE", nil +} + +// obrimCodecDecodeBase64 decodes Base64 encoded data. +func obrimCodecDecodeBase64(config ObrimCodecConfig) (map[string]any, string, error) { + value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) + + decoded, err := base64.StdEncoding.DecodeString(value) + if err != nil { + return nil, "FAILED_BASE64_DECODE", err + } + + return map[string]any{ + "operation": "decode", + "format": "base64", + "value": string(decoded), + }, "SUCCESS_BASE64_DECODE", nil +} + +// obrimCodecDecodeSqids decodes Sqids encoded data using deterministic length validation. +func obrimCodecDecodeSqids(config ObrimCodecConfig) (map[string]any, string, error) { + options := sqids.Options{ + MinLength: uint8(config.Length), + Alphabet: obrimCodecAlphabet(config.Charset), + Blocklist: []string{}, + } + + instance, err := sqids.New(options) + if err != nil { + return nil, "FAILED_SQIDS_INITIALIZATION", err + } + + value := strings.TrimPrefix(obrimCodecString(config.Data), config.Salt) + + decoded := instance.Decode(value) + if len(decoded) == 0 { + return nil, "FAILED_SQIDS_DECODE", errors.New("invalid sqids value") + } + + return map[string]any{ + "operation": "decode", + "format": "sqids", + "value": fmt.Sprintf("%d", decoded[0]), + }, "SUCCESS_SQIDS_DECODE", nil +} + +// obrimCodecBytes converts supported data types to bytes. +func obrimCodecBytes(data any) []byte { + switch value := data.(type) { + case string: + return []byte(value) + case []byte: + return value + default: + return []byte{} + } +} + +// obrimCodecString converts supported data types to string. +func obrimCodecString(data any) string { + switch value := data.(type) { + case string: + return value + case []byte: + return string(value) + default: + return "" + } +} + +// obrimCodecApplyCase applies output casing rules. +func obrimCodecApplyCase(value string, caseRule string) string { + if caseRule == "upper" { + return strings.ToUpper(value) + } + + return strings.ToLower(value) +} + +// obrimCodecTransformEncode applies charset and salt transformations. +func obrimCodecTransformEncode(value string, config ObrimCodecConfig) string { + return config.Salt + config.Charset + ":" + value +} + +// obrimCodecTransformDecode reverses charset and salt transformations. +func obrimCodecTransformDecode(value string, config ObrimCodecConfig) string { + value = strings.TrimPrefix(value, config.Salt) + value = strings.TrimPrefix(value, config.Charset+":") + return value +} + +// obrimCodecAlphabet resolves Sqids alphabet. +func obrimCodecAlphabet(charset string) string { + if charset == "" { + return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + } + + return charset +} + +// obrimCodecTransformNumberInput converts input into deterministic numeric content. +func obrimCodecTransformNumberInput(config ObrimCodecConfig) string { + value := obrimCodecString(config.Data) + + if _, err := strconv.ParseUint(value, 10, 64); err == nil { + return value + } + + return fmt.Sprintf("%d", len(value)+len(config.Salt)+len(config.Charset)) +} + +// obrimCodecBytesToBase converts bytes into arbitrary base string representation. +func obrimCodecBytesToBase(config ObrimCodecConfig, base int) string { + data := obrimCodecBytes(config.Data) + + var builder strings.Builder + + for _, item := range data { + builder.WriteString(strconv.FormatInt(int64(item), base)) + } + + return builder.String() +} diff --git a/essential/visible/service/helper/datetime/datetime.go b/essential/visible/service/helper/datetime/datetime.go index e69de29..eb8dadc 100644 --- a/essential/visible/service/helper/datetime/datetime.go +++ b/essential/visible/service/helper/datetime/datetime.go @@ -0,0 +1,276 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - datetime +| +| Purpose: +| - Retrieve and format the current date and time from either the host +| system clock or a trusted framework-managed NTP source. +| +| Guideline: +| - Use local for host system clock retrieval. +| - Use trusted for framework-managed NTP retrieval. +| - Only use supported framework date/time format patterns. +| - All responses must be returned as standardized JSON objects. +| +| Example: +| - ObrimDatetime("local", map[string]any{"format":"yyyy-MM-dd"}) +| - ObrimDatetime("trusted", map[string]any{"format":"timestampsec"}) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package datetime + +import ( + "encoding/json" + "errors" + "net" + "time" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/status" +) + +// ObrimDatetimePayload represents datetime payload data. +type ObrimDatetimePayload struct { + Value string `json:"value"` +} + +// ObrimDatetimeOutput represents utility output structure. +type ObrimDatetimeOutput struct { + Status bool `json:"status"` + Code string `json:"code"` + Payload *ObrimDatetimePayload `json:"payload"` +} + +// obrimDatetimePatternMap stores framework-supported format mappings. +var obrimDatetimePatternMap = map[string]string{ + "yyyy-MM-dd": "2006-01-02", + "MMM dd, yyyy": "Jan 02, 2006", + "MMMM dd, yyyy": "January 02, 2006", + "EEE, MMM dd, yyyy": "Mon, Jan 02, 2006", + "EEE, MMMM dd, yyyy": "Mon, January 02, 2006", + "EEEE, MMM dd, yyyy": "Monday, Jan 02, 2006", + "EEEE, MMMM dd, yyyy": "Monday, January 02, 2006", + "HH:mm:ss": "15:04:05", + "hh:mm:ss a": "03:04:05 PM", + "yyyy-MM-dd HH:mm:ss": "2006-01-02 15:04:05", + "yyyy-MM-dd HH:mm:ss z": "2006-01-02 15:04:05 MST", + "yyyy-MM-dd'T'HH:mm:ssXXX": "2006-01-02T15:04:05Z07:00", +} + +// ObrimDatetime retrieves and formats current date and time. +func ObrimDatetime(datetimeType string, config map[string]any) string { + status.ObrimStatus("INFO", "Initializing datetime utility.") + log.ObrimLog("INIT", "Datetime utility initialized.") + + if err := obrimDatetimeValidate(datetimeType, config); err != nil { + status.ObrimStatus("ERROR", err.Error()) + log.ObrimLog("ERROR", err.Error()) + + response := obrimDatetimeResponse(false, "FAILED_"+err.Error(), nil) + return response + } + + format := config["format"].(string) + + var currentTime time.Time + var err error + + switch datetimeType { + case "local": + currentTime, err = obrimDatetimeLocal() + + case "trusted": + currentTime, err = obrimDatetimeTrusted() + + default: + err = errors.New("INVALID_TYPE") + } + + if err != nil { + status.ObrimStatus("ERROR", err.Error()) + log.ObrimLog("ERROR", err.Error()) + + response := obrimDatetimeResponse(false, "FAILED_"+err.Error(), nil) + return response + } + + value, err := obrimDatetimeFormatApply(currentTime, format) + if err != nil { + status.ObrimStatus("ERROR", err.Error()) + log.ObrimLog("ERROR", err.Error()) + + response := obrimDatetimeResponse(false, "FAILED_"+err.Error(), nil) + return response + } + + payload := &ObrimDatetimePayload{ + Value: value, + } + + status.ObrimStatus("SUCCESS", "Datetime retrieved successfully.") + log.ObrimLog("SUCCESS", "Datetime retrieved successfully.") + + return obrimDatetimeResponse( + true, + "SUCCESS_DATETIME_RETRIEVED", + payload, + ) +} + +// obrimDatetimeValidate validates utility inputs. +func obrimDatetimeValidate(datetimeType string, config map[string]any) error { + if datetimeType != "local" && datetimeType != "trusted" { + return errors.New("INVALID_TYPE") + } + + formatValue, exists := config["format"] + if !exists { + return errors.New("INVALID_FORMAT") + } + + format, ok := formatValue.(string) + if !ok { + return errors.New("INVALID_FORMAT") + } + + if !obrimDatetimePatternValidate(format) { + return errors.New("INVALID_FORMAT") + } + + return nil +} + +// obrimDatetimePatternValidate validates supported patterns. +func obrimDatetimePatternValidate(pattern string) bool { + _, exists := obrimDatetimePatternMap[pattern] + return exists || pattern == "timestampsec" || pattern == "timestampmil" +} + +// obrimDatetimePatternResolve resolves framework patterns. +func obrimDatetimePatternResolve(pattern string) (string, error) { + if pattern == "timestampsec" || pattern == "timestampmil" { + return pattern, nil + } + + layout, exists := obrimDatetimePatternMap[pattern] + if !exists { + return "", errors.New("INVALID_FORMAT") + } + + return layout, nil +} + +// obrimDatetimeFormatApply applies formatting. +func obrimDatetimeFormatApply(value time.Time, pattern string) (string, error) { + layout, err := obrimDatetimePatternResolve(pattern) + if err != nil { + return "", err + } + + switch pattern { + case "timestampsec": + return time.Unix(value.Unix(), 0).Format("1136239445"), nil + + case "timestampmil": + return time.UnixMilli(value.UnixMilli()).Format("1136239445000"), nil + + default: + return value.Format(layout), nil + } +} + +// obrimDatetimeLocal retrieves local system time. +func obrimDatetimeLocal() (time.Time, error) { + return time.Now(), nil +} + +// obrimDatetimeTrusted retrieves trusted time. +func obrimDatetimeTrusted() (time.Time, error) { + return obrimDatetimeTrustedSync() +} + +// obrimDatetimeTrustedSync synchronizes trusted NTP time. +func obrimDatetimeTrustedSync() (time.Time, error) { + connection, err := net.DialTimeout( + "udp", + "time.google.com:123", + 5*time.Second, + ) + if err != nil { + return time.Time{}, errors.New("TRUSTED_TIME_RETRIEVAL") + } + + defer connection.Close() + + request := make([]byte, 48) + request[0] = 0x1B + + if _, err = connection.Write(request); err != nil { + return time.Time{}, errors.New("TRUSTED_TIME_RETRIEVAL") + } + + if err = connection.SetDeadline(time.Now().Add(5 * time.Second)); err != nil { + return time.Time{}, errors.New("TRUSTED_TIME_RETRIEVAL") + } + + response := make([]byte, 48) + + if _, err = connection.Read(response); err != nil { + return time.Time{}, errors.New("TRUSTED_TIME_RETRIEVAL") + } + + seconds := uint64(response[40])<<24 | + uint64(response[41])<<16 | + uint64(response[42])<<8 | + uint64(response[43]) + + const ntpEpochOffset = 2208988800 + + unixSeconds := int64(seconds) - ntpEpochOffset + + return time.Unix(unixSeconds, 0).UTC(), nil +} + +// obrimDatetimeResponse builds standardized responses. +func obrimDatetimeResponse( + statusValue bool, + code string, + payload *ObrimDatetimePayload, +) string { + response := ObrimDatetimeOutput{ + Status: statusValue, + Code: code, + Payload: payload, + } + + data, err := json.Marshal(response) + if err != nil { + fallback := ObrimDatetimeOutput{ + Status: false, + Code: "FAILED_RESPONSE_BUILD", + Payload: nil, + } + + data, _ = json.Marshal(fallback) + } + + return string(data) +} diff --git a/essential/visible/service/helper/filesystem/filesystem.go b/essential/visible/service/helper/filesystem/filesystem.go index e69de29..6c66e27 100644 --- a/essential/visible/service/helper/filesystem/filesystem.go +++ b/essential/visible/service/helper/filesystem/filesystem.go @@ -0,0 +1,677 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Filesystem +| +| Purpose: +| - Provide reusable, OS-agnostic filesystem operations through a unified execution interface. +| +| Guideline: +| - Use for deterministic filesystem listing, validation, creation, deletion, and permission operations. +| - Execute exactly one operation per invocation. +| - Validate configuration before execution. +| - Return structured output for all execution paths. +| - Remain independent from runtime execution layers. +| +| Example: +| - ObrimFilesystem("list", map[string]any{"strategy":"user"}) +| - ObrimFilesystem("create", map[string]any{"entity":"directory","name":"example"}) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package filesystem + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "sort" + "strconv" + "strings" + "time" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/status" +) + +type ObrimFilesystemResult struct { + Status bool `json:"status"` + Code string `json:"code"` + Payload any `json:"payload"` +} + +type obrimFilesystemEntry struct { + Name string `json:"name"` + Path string `json:"path"` + Entity string `json:"entity"` + Size int64 `json:"size"` + Modified time.Time `json:"modified"` + Created time.Time `json:"created"` + IsHidden bool `json:"hidden"` + IsSymlink bool `json:"symlink"` + Permissions string `json:"permission"` +} + +var obrimFilesystemSupportedTypes = map[string]bool{ + "list": true, + "check": true, + "create": true, + "delete": true, + "permission": true, +} + +var obrimFilesystemAllowedKeys = map[string]map[string]bool{ + "list": { + "entity": true, "strategy": true, "base": true, "name": true, + "recursive": true, "include_hidden": true, "sort_by": true, + "sort_order": true, "filter_pattern": true, "follow_symlink": true, + "absolute_path": true, + }, + "check": { + "entity": true, "strategy": true, "base": true, "name": true, + "readable": true, "writable": true, + }, + "create": { + "entity": true, "strategy": true, "base": true, "name": true, + "hidden": true, + }, + "delete": { + "entity": true, "strategy": true, "base": true, "name": true, + "recursive": true, + }, + "permission": { + "entity": true, "strategy": true, "base": true, "name": true, + "mode": true, "permission": true, + }, +} + +// ObrimFilesystem executes a filesystem operation and returns a structured result. +func ObrimFilesystem(operationType string, config map[string]any) map[string]any { + log.ObrimLog("INIT", fmt.Sprintf("filesystem operation: %s", operationType)) + + if err := obrimFilesystemValidate(operationType, config); err != nil { + status.ObrimStatus("ERROR", err.Error()) + log.ObrimLog("ERROR", err.Error()) + + return map[string]any{ + "status": false, + "code": "FAILED_VALIDATION", + "payload": nil, + } + } + + switch operationType { + case "list": + return obrimFilesystemList(config) + + case "check": + return obrimFilesystemCheck(config) + + case "create": + return obrimFilesystemCreate(config) + + case "delete": + return obrimFilesystemDelete(config) + + case "permission": + return obrimFilesystemPermission(config) + + default: + status.ObrimStatus("ERROR", "Unsupported operation.") + return map[string]any{ + "status": false, + "code": "FAILED_UNSUPPORTED_OPERATION", + "payload": nil, + } + } +} + +// obrimFilesystemValidate validates operation type and configuration. +func obrimFilesystemValidate(operationType string, config map[string]any) error { + if !obrimFilesystemSupportedTypes[operationType] { + return errors.New("unsupported operation type") + } + + allowed := obrimFilesystemAllowedKeys[operationType] + + for key := range config { + if !allowed[key] { + return fmt.Errorf("unsupported config key: %s", key) + } + } + + if operationType != "list" { + if _, exists := config["name"]; !exists { + return errors.New("name is required") + } + } + + if operationType == "create" || operationType == "delete" { + entity := fmt.Sprintf("%v", config["entity"]) + + if entity != "file" && entity != "directory" { + return errors.New("invalid entity") + } + } + + if operationType == "permission" { + mode := fmt.Sprintf("%v", config["mode"]) + + if mode != "read" && mode != "write" { + return errors.New("invalid permission mode") + } + + if mode == "write" { + if err := obrimFilesystemPermissionValidate(config); err != nil { + return err + } + } + } + + return nil +} + +// obrimFilesystemResolve resolves and normalizes filesystem paths. +func obrimFilesystemResolve(config map[string]any) (string, error) { + strategy := fmt.Sprintf("%v", config["strategy"]) + + var base string + + switch strategy { + case "", "user": + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + + base = home + + case "custom": + base = fmt.Sprintf("%v", config["base"]) + + if base == "" { + return "", errors.New("base path required") + } + + default: + return "", errors.New("invalid strategy") + } + + name := fmt.Sprintf("%v", config["name"]) + + return filepath.Clean(filepath.Join(base, name)), nil +} + +// obrimFilesystemPayload builds standardized payload structures. +func obrimFilesystemPayload(data map[string]any) map[string]any { + return data +} + +// obrimFilesystemEntityType determines filesystem entity type. +func obrimFilesystemEntityType(path string) string { + info, err := os.Stat(path) + + if err != nil { + return "unknown" + } + + if info.IsDir() { + return "directory" + } + + return "file" +} + +// obrimFilesystemPermissionValidate validates permission specifications. +func obrimFilesystemPermissionValidate(config map[string]any) error { + permission := fmt.Sprintf("%v", config["permission"]) + + if permission == "" { + return errors.New("permission is required") + } + + _, err := strconv.ParseUint(permission, 8, 32) + + return err +} + +// obrimFilesystemList executes filesystem listing operations. +func obrimFilesystemList(config map[string]any) map[string]any { + base, err := obrimFilesystemResolve(map[string]any{ + "strategy": config["strategy"], + "base": config["base"], + "name": "", + }) + + if err != nil { + return map[string]any{ + "status": false, + "code": "FAILED_PATH_RESOLUTION", + "payload": nil, + } + } + + entries, err := obrimFilesystemListTraverse(base, config) + + if err != nil { + return map[string]any{ + "status": false, + "code": "FAILED_LIST", + "payload": nil, + } + } + + entries = obrimFilesystemListFilter(entries, config) + entries = obrimFilesystemListSort(entries, config) + + status.ObrimStatus("SUCCESS", "Filesystem listing completed.") + + return map[string]any{ + "status": true, + "code": "SUCCESS_LIST", + "payload": obrimFilesystemPayload(map[string]any{ + "entries": entries, + "total": len(entries), + "recursive": config["recursive"] == true, + "base_path": base, + }), + } +} + +// obrimFilesystemListTraverse traverses filesystem entities. +func obrimFilesystemListTraverse(base string, config map[string]any) ([]obrimFilesystemEntry, error) { + recursive := config["recursive"] == true + includeHidden := config["include_hidden"] == true + followSymlink := config["follow_symlink"] == true + absolute := config["absolute_path"] == true + + var entries []obrimFilesystemEntry + + if recursive { + err := filepath.Walk(base, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil + } + + if path == base { + return nil + } + + if !includeHidden && strings.HasPrefix(info.Name(), ".") { + if info.IsDir() { + return filepath.SkipDir + } + return nil + } + + if info.Mode()&os.ModeSymlink != 0 && !followSymlink { + return nil + } + + entryPath := path + + if !absolute { + entryPath = info.Name() + } + + entries = append(entries, obrimFilesystemEntry{ + Name: info.Name(), + Path: entryPath, + Entity: obrimFilesystemEntityType(path), + Size: info.Size(), + Modified: info.ModTime(), + Created: info.ModTime(), + IsHidden: strings.HasPrefix(info.Name(), "."), + IsSymlink: info.Mode()&os.ModeSymlink != 0, + Permissions: info.Mode().Perm().String(), + }) + + return nil + }) + + return entries, err + } + + list, err := os.ReadDir(base) + + if err != nil { + return nil, err + } + + for _, item := range list { + if !includeHidden && strings.HasPrefix(item.Name(), ".") { + continue + } + + info, err := item.Info() + + if err != nil { + continue + } + + path := filepath.Join(base, item.Name()) + + entryPath := path + + if !absolute { + entryPath = item.Name() + } + + entries = append(entries, obrimFilesystemEntry{ + Name: item.Name(), + Path: entryPath, + Entity: obrimFilesystemEntityType(path), + Size: info.Size(), + Modified: info.ModTime(), + Created: info.ModTime(), + IsHidden: strings.HasPrefix(item.Name(), "."), + IsSymlink: info.Mode()&os.ModeSymlink != 0, + Permissions: info.Mode().Perm().String(), + }) + } + + return entries, nil +} + +// obrimFilesystemListFilter applies entity and pattern filtering. +func obrimFilesystemListFilter(entries []obrimFilesystemEntry, config map[string]any) []obrimFilesystemEntry { + entity := fmt.Sprintf("%v", config["entity"]) + pattern := fmt.Sprintf("%v", config["filter_pattern"]) + + var filtered []obrimFilesystemEntry + + for _, entry := range entries { + if entity != "" && entry.Entity != entity { + continue + } + + if pattern != "" { + match, _ := filepath.Match(pattern, entry.Name) + + if !match { + continue + } + } + + filtered = append(filtered, entry) + } + + return filtered +} + +// obrimFilesystemListSort applies result sorting behavior. +func obrimFilesystemListSort(entries []obrimFilesystemEntry, config map[string]any) []obrimFilesystemEntry { + sortBy := fmt.Sprintf("%v", config["sort_by"]) + order := fmt.Sprintf("%v", config["sort_order"]) + + sort.Slice(entries, func(i, j int) bool { + result := false + + switch sortBy { + case "size": + result = entries[i].Size < entries[j].Size + + case "modified": + result = entries[i].Modified.Before(entries[j].Modified) + + case "created": + result = entries[i].Created.Before(entries[j].Created) + + default: + result = entries[i].Name < entries[j].Name + } + + if order == "desc" { + return !result + } + + return result + }) + + return entries +} + +// obrimFilesystemCheck executes filesystem validation operations. +func obrimFilesystemCheck(config map[string]any) map[string]any { + path, err := obrimFilesystemResolve(config) + + if err != nil { + return map[string]any{"status": false, "code": "FAILED_PATH_RESOLUTION", "payload": nil} + } + + _, err = os.Stat(path) + + exists := err == nil + + readable, writable := obrimFilesystemCheckAccess(path) + + return map[string]any{ + "status": true, + "code": "SUCCESS_CHECK", + "payload": map[string]any{ + "path": path, + "exists": exists, + "entity": obrimFilesystemEntityType(path), + "readable": readable, + "writable": writable, + }, + } +} + +// obrimFilesystemCheckAccess verifies filesystem accessibility. +func obrimFilesystemCheckAccess(path string) (bool, bool) { + readable := true + writable := true + + file, err := os.Open(path) + + if err != nil { + readable = false + } else { + _ = file.Close() + } + + file, err = os.OpenFile(path, os.O_WRONLY, 0) + + if err != nil { + writable = false + } else { + _ = file.Close() + } + + return readable, writable +} + +// obrimFilesystemCreate executes filesystem entity creation operations. +func obrimFilesystemCreate(config map[string]any) map[string]any { + path, err := obrimFilesystemResolve(config) + + if err != nil { + return map[string]any{"status": false, "code": "FAILED_PATH_RESOLUTION", "payload": nil} + } + + entity := fmt.Sprintf("%v", config["entity"]) + + if entity == "file" { + err = obrimFilesystemCreateFile(path) + } else { + err = obrimFilesystemCreateDirectory(path) + } + + if err != nil { + return map[string]any{"status": false, "code": "FAILED_CREATE", "payload": nil} + } + + return map[string]any{ + "status": true, + "code": "SUCCESS_CREATE", + "payload": map[string]any{ + "path": path, + "entity": entity, + "hidden": config["hidden"] == true, + "created": true, + }, + } +} + +// obrimFilesystemCreateFile creates a filesystem file. +func obrimFilesystemCreateFile(path string) error { + if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + return err + } + + file, err := os.Create(path) + + if err != nil { + return err + } + + return file.Close() +} + +// obrimFilesystemCreateDirectory creates a filesystem directory. +func obrimFilesystemCreateDirectory(path string) error { + return os.MkdirAll(path, 0755) +} + +// obrimFilesystemDelete executes filesystem entity deletion operations. +func obrimFilesystemDelete(config map[string]any) map[string]any { + path, err := obrimFilesystemResolve(config) + + if err != nil { + return map[string]any{"status": false, "code": "FAILED_PATH_RESOLUTION", "payload": nil} + } + + entity := fmt.Sprintf("%v", config["entity"]) + + if entity == "file" { + err = obrimFilesystemDeleteFile(path) + } else { + err = obrimFilesystemDeleteDirectory(path, config["recursive"] == true) + } + + if err != nil { + return map[string]any{"status": false, "code": "FAILED_DELETE", "payload": nil} + } + + return map[string]any{ + "status": true, + "code": "SUCCESS_DELETE", + "payload": map[string]any{ + "path": path, + "entity": entity, + "deleted": true, + }, + } +} + +// obrimFilesystemDeleteFile deletes a filesystem file. +func obrimFilesystemDeleteFile(path string) error { + return os.Remove(path) +} + +// obrimFilesystemDeleteDirectory deletes a filesystem directory. +func obrimFilesystemDeleteDirectory(path string, recursive bool) error { + if recursive { + return os.RemoveAll(path) + } + + return os.Remove(path) +} + +// obrimFilesystemPermission executes filesystem permission operations. +func obrimFilesystemPermission(config map[string]any) map[string]any { + path, err := obrimFilesystemResolve(config) + + if err != nil { + return map[string]any{"status": false, "code": "FAILED_PATH_RESOLUTION", "payload": nil} + } + + mode := fmt.Sprintf("%v", config["mode"]) + + if mode == "read" { + return obrimFilesystemPermissionRead(path) + } + + return obrimFilesystemPermissionWrite(path, fmt.Sprintf("%v", config["permission"])) +} + +// obrimFilesystemPermissionRead retrieves filesystem permissions. +func obrimFilesystemPermissionRead(path string) map[string]any { + info, err := os.Stat(path) + + if err != nil { + return map[string]any{"status": false, "code": "FAILED_PERMISSION_READ", "payload": nil} + } + + return map[string]any{ + "status": true, + "code": "SUCCESS_PERMISSION_READ", + "payload": map[string]any{ + "path": path, + "permission": info.Mode().Perm().String(), + "mode": "read", + "updated": false, + }, + } +} + +// obrimFilesystemPermissionWrite updates filesystem permissions. +func obrimFilesystemPermissionWrite(path string, permission string) map[string]any { + if runtime.GOOS == "windows" { + return map[string]any{ + "status": false, + "code": "FAILED_PERMISSION_UNSUPPORTED", + "payload": nil, + } + } + + value, err := strconv.ParseUint(permission, 8, 32) + + if err != nil { + return map[string]any{ + "status": false, + "code": "FAILED_PERMISSION_VALIDATION", + "payload": nil, + } + } + + err = os.Chmod(path, os.FileMode(value)) + + if err != nil { + return map[string]any{ + "status": false, + "code": "FAILED_PERMISSION_WRITE", + "payload": nil, + } + } + + return map[string]any{ + "status": true, + "code": "SUCCESS_PERMISSION_WRITE", + "payload": map[string]any{ + "path": path, + "permission": permission, + "mode": "write", + "updated": true, + }, + } +} diff --git a/essential/visible/service/helper/hash/hash.go b/essential/visible/service/helper/hash/hash.go index e69de29..647f370 100644 --- a/essential/visible/service/helper/hash/hash.go +++ b/essential/visible/service/helper/hash/hash.go @@ -0,0 +1,507 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Hash +| +| Purpose: +| - Generate and verify cryptographic hash values using standard or +| salted hashing methods. +| +| Guideline: +| - Use for deterministic hashing workflows. +| - Use for salted hashing workflows requiring verification support. +| - Use for integrity verification and fingerprint generation. +| - Accept exactly two primary parameters: type and config. +| +| Example: +| - ObrimHash("calculate", config) +| - ObrimHash("compare", config) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package hash + +import ( + "crypto/rand" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "strings" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/retriever" + "go/module/essential/visible/service/helper/status" +) + +// ObrimHash processes hash generation and verification requests. +func ObrimHash( + hashType string, + config map[string]any, +) map[string]any { + status.ObrimStatus("INFO", "Hash utility execution started.") + log.ObrimLog("INIT", "Hash utility execution started.") + + _, _ = retriever.ObrimRetriever( + "json", + map[string]any{ + "resource": "framework/metadata", + "path": "name", + }, + ) + + if !obrimHashValidateType(hashType) { + status.ObrimStatus("ERROR", "Invalid hash type.") + log.ObrimLog("ERROR", "Invalid hash type.") + return obrimHashBuildErrorPayload("FAILED_INVALID_TYPE") + } + + if !obrimHashValidateConfig(hashType, config) { + status.ObrimStatus("ERROR", "Invalid configuration.") + log.ObrimLog("ERROR", "Invalid configuration.") + return obrimHashBuildErrorPayload("FAILED_INVALID_CONFIG") + } + + mode := config["mode"].(string) + + if !obrimHashValidateMode(mode) { + status.ObrimStatus("ERROR", "Invalid mode.") + log.ObrimLog("ERROR", "Invalid mode.") + return obrimHashBuildErrorPayload("FAILED_INVALID_MODE") + } + + algorithm := config["algorithm"].(string) + + if !obrimHashValidateAlgorithm(mode, algorithm) { + status.ObrimStatus("ERROR", "Invalid algorithm.") + log.ObrimLog("ERROR", "Invalid algorithm.") + return obrimHashBuildErrorPayload("FAILED_INVALID_ALGORITHM") + } + + switch hashType { + case "calculate": + return obrimHashCalculate(config) + + case "compare": + return obrimHashCompare(config) + + default: + return obrimHashBuildErrorPayload("FAILED_INVALID_TYPE") + } +} + +// obrimHashValidateType validates operation type. +func obrimHashValidateType(hashType string) bool { + switch hashType { + case "calculate", "compare": + return true + default: + return false + } +} + +// obrimHashValidateMode validates hashing mode. +func obrimHashValidateMode(mode string) bool { + switch mode { + case "standard", "salted": + return true + default: + return false + } +} + +// obrimHashValidateConfig validates configuration keys and values. +func obrimHashValidateConfig( + hashType string, + config map[string]any, +) bool { + if config == nil { + return false + } + + // Mutable variable holding supported keys. + supportedKeys := map[string]bool{ + "mode": true, + "algorithm": true, + "value": true, + "hash": true, + "salt": true, + } + + for key := range config { + if !supportedKeys[key] { + return false + } + } + + modeValue, modeExists := config["mode"] + algorithmValue, algorithmExists := config["algorithm"] + valueValue, valueExists := config["value"] + + if !modeExists || !algorithmExists || !valueExists { + return false + } + + mode, modeOK := modeValue.(string) + algorithm, algorithmOK := algorithmValue.(string) + value, valueOK := valueValue.(string) + + if !modeOK || !algorithmOK || !valueOK { + return false + } + + if mode == "" || algorithm == "" || value == "" { + return false + } + + if hashType == "calculate" { + if mode == "standard" { + if _, exists := config["salt"]; exists { + return false + } + } + + return true + } + + if hashType == "compare" { + hashValue, hashExists := config["hash"] + + if !hashExists { + return false + } + + hashString, hashOK := hashValue.(string) + + if !hashOK || hashString == "" { + return false + } + + if mode == "standard" { + if _, exists := config["salt"]; exists { + return false + } + } + + if mode == "salted" { + saltValue, saltExists := config["salt"] + + if !saltExists { + return false + } + + saltString, saltOK := saltValue.(string) + + if !saltOK || saltString == "" { + return false + } + } + + return true + } + + return false +} + +// obrimHashValidateAlgorithm validates hashing algorithm selection. +func obrimHashValidateAlgorithm( + mode string, + algorithm string, +) bool { + if mode == "standard" { + switch algorithm { + case "sha256", "sha512": + return true + } + } + + if mode == "salted" { + switch algorithm { + case "salted_sha256", "salted_sha512": + return true + } + } + + return false +} + +// obrimHashGenerateHash executes the selected hashing algorithm. +func obrimHashGenerateHash( + algorithm string, + value string, + salt string, +) (string, bool) { + switch algorithm { + case "sha256": + sum := sha256.Sum256([]byte(value)) + return hex.EncodeToString(sum[:]), true + + case "sha512": + sum := sha512.Sum512([]byte(value)) + return hex.EncodeToString(sum[:]), true + + case "salted_sha256": + sum := sha256.Sum256([]byte(value + salt)) + return hex.EncodeToString(sum[:]), true + + case "salted_sha512": + sum := sha512.Sum512([]byte(value + salt)) + return hex.EncodeToString(sum[:]), true + + default: + return "", false + } +} + +// obrimHashBuildSuccessPayload constructs success response payloads. +func obrimHashBuildSuccessPayload( + code string, + payload map[string]any, +) map[string]any { + return map[string]any{ + "status": true, + "code": code, + "payload": payload, + } +} + +// obrimHashBuildErrorPayload constructs error response payloads. +func obrimHashBuildErrorPayload(code string) map[string]any { + return map[string]any{ + "status": false, + "code": code, + "payload": nil, + } +} + +// obrimHashCalculate processes hash generation requests. +func obrimHashCalculate( + config map[string]any, +) map[string]any { + mode := config["mode"].(string) + + switch mode { + case "standard": + return obrimHashCalculateStandard(config) + + case "salted": + return obrimHashCalculateSalted(config) + + default: + return obrimHashBuildErrorPayload("FAILED_INVALID_MODE") + } +} + +// obrimHashCalculateStandard generates a deterministic hash. +func obrimHashCalculateStandard( + config map[string]any, +) map[string]any { + algorithm := config["algorithm"].(string) + value := config["value"].(string) + + hashValue, success := obrimHashGenerateHash( + algorithm, + value, + "", + ) + + if !success { + return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION") + } + + payload := map[string]any{ + "algorithm": algorithm, + "hash": hashValue, + } + + status.ObrimStatus("SUCCESS", "Hash generated.") + log.ObrimLog("SUCCESS", "Standard hash generated.") + + return obrimHashBuildSuccessPayload( + "SUCCESS_CALCULATE_STANDARD", + payload, + ) +} + +// obrimHashCalculateSalted generates a salted hash and salt pair. +func obrimHashCalculateSalted( + config map[string]any, +) map[string]any { + algorithm := config["algorithm"].(string) + value := config["value"].(string) + + // Mutable variable holding salt value. + saltValue := "" + + if suppliedSalt, exists := config["salt"]; exists { + saltString, ok := suppliedSalt.(string) + + if !ok || saltString == "" { + return obrimHashBuildErrorPayload("FAILED_INVALID_SALT") + } + + saltValue = saltString + } else { + generatedSalt, success := obrimHashGenerateSalt() + + if !success { + return obrimHashBuildErrorPayload("FAILED_SALT_GENERATION") + } + + saltValue = generatedSalt + } + + hashValue, success := obrimHashGenerateHash( + algorithm, + value, + saltValue, + ) + + if !success { + return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION") + } + + payload := map[string]any{ + "algorithm": algorithm, + "hash": hashValue, + "salt": saltValue, + } + + status.ObrimStatus("SUCCESS", "Salted hash generated.") + log.ObrimLog("SUCCESS", "Salted hash generated.") + + return obrimHashBuildSuccessPayload( + "SUCCESS_CALCULATE_SALTED", + payload, + ) +} + +// obrimHashGenerateSalt generates a cryptographically secure salt. +func obrimHashGenerateSalt() (string, bool) { + // Mutable variable holding salt bytes. + saltBytes := make([]byte, 32) + + _, err := rand.Read(saltBytes) + + if err != nil { + return "", false + } + + return hex.EncodeToString(saltBytes), true +} + +// obrimHashCompare processes hash verification requests. +func obrimHashCompare( + config map[string]any, +) map[string]any { + mode := config["mode"].(string) + + switch mode { + case "standard": + return obrimHashCompareStandard(config) + + case "salted": + return obrimHashCompareSalted(config) + + default: + return obrimHashBuildErrorPayload("FAILED_INVALID_MODE") + } +} + +// obrimHashCompareStandard regenerates a standard hash for verification. +func obrimHashCompareStandard( + config map[string]any, +) map[string]any { + algorithm := config["algorithm"].(string) + value := config["value"].(string) + hashValue := config["hash"].(string) + + regeneratedHash, success := obrimHashGenerateHash( + algorithm, + value, + "", + ) + + if !success { + return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION") + } + + matched := obrimHashVerify( + regeneratedHash, + hashValue, + ) + + payload := map[string]any{ + "algorithm": algorithm, + "matched": matched, + "hash": hashValue, + } + + return obrimHashBuildSuccessPayload( + "SUCCESS_COMPARE_STANDARD", + payload, + ) +} + +// obrimHashCompareSalted regenerates a salted hash for verification. +func obrimHashCompareSalted( + config map[string]any, +) map[string]any { + algorithm := config["algorithm"].(string) + value := config["value"].(string) + hashValue := config["hash"].(string) + saltValue := config["salt"].(string) + + regeneratedHash, success := obrimHashGenerateHash( + algorithm, + value, + saltValue, + ) + + if !success { + return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION") + } + + matched := obrimHashVerify( + regeneratedHash, + hashValue, + ) + + payload := map[string]any{ + "algorithm": algorithm, + "matched": matched, + "hash": hashValue, + "salt": saltValue, + } + + return obrimHashBuildSuccessPayload( + "SUCCESS_COMPARE_SALTED", + payload, + ) +} + +// obrimHashVerify compares regenerated and supplied hash values. +func obrimHashVerify( + regeneratedHash string, + suppliedHash string, +) bool { + return strings.Compare( + regeneratedHash, + suppliedHash, + ) == 0 +} diff --git a/essential/visible/service/helper/key/key.go b/essential/visible/service/helper/key/key.go index e69de29..6fde82c 100644 --- a/essential/visible/service/helper/key/key.go +++ b/essential/visible/service/helper/key/key.go @@ -0,0 +1,348 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Key +| +| Purpose: +| - Generate cryptographic key material using a type-driven dispatch model. +| +| Guideline: +| - Use explicit configuration values only. +| - Validate all inputs before generation. +| - Reject unsupported or irrelevant configuration fields. +| - Use centralized dispatch for workflow execution. +| +| Example: +| - ObrimKey("symmetric", map[string]any{ +| "algorithm": "aes", +| "key_size": 256, +| }) +| +| - ObrimKey("asymmetric", map[string]any{ +| "algorithm": "ecc", +| }) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package key + +import ( + "crypto/aes" + "crypto/ed25519" + "crypto/rand" + "encoding/base64" + "fmt" + "strings" + "time" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/status" +) + +const ( + obrimKeyTypeSymmetric = "symmetric" + obrimKeyTypeAsymmetric = "asymmetric" + + obrimKeyAlgorithmAES = "aes" + obrimKeyAlgorithmECC = "ecc" + + obrimKeyCurveEdDSA = "eddsa" +) + +// ObrimKey dispatches key generation requests and orchestrates validation, generation, and response construction. +func ObrimKey(keyType string, config map[string]any) map[string]any { + log.ObrimLog("INIT", "Key generation request received.") + status.ObrimStatus("INFO", "Validating key generation request.") + + if response := obrimKeyValidate(keyType, config); response != nil { + return response + } + + return obrimKeyDispatch(keyType, config) +} + +// obrimKeyValidate validates common request structure and schema integrity. +func obrimKeyValidate(keyType string, config map[string]any) map[string]any { + if strings.TrimSpace(keyType) == "" { + return obrimKeyBuildError("FAILED_TYPE_REQUIRED") + } + + if config == nil { + return obrimKeyBuildError("FAILED_CONFIG_REQUIRED") + } + + normalizedType := strings.ToLower(strings.TrimSpace(keyType)) + + switch normalizedType { + case obrimKeyTypeSymmetric: + return obrimKeyValidateSymmetricConfig(config) + + case obrimKeyTypeAsymmetric: + return obrimKeyValidateAsymmetricConfig(config) + + default: + return obrimKeyBuildError("FAILED_UNSUPPORTED_TYPE") + } +} + +// obrimKeyDispatch routes execution to the appropriate cryptographic workflow. +func obrimKeyDispatch(keyType string, config map[string]any) map[string]any { + normalizedType := strings.ToLower(strings.TrimSpace(keyType)) + + switch normalizedType { + case obrimKeyTypeSymmetric: + return obrimKeyGenerateSymmetric(config) + + case obrimKeyTypeAsymmetric: + return obrimKeyGenerateAsymmetric(config) + + default: + return obrimKeyBuildError("FAILED_UNSUPPORTED_TYPE") + } +} + +// obrimKeyValidateSymmetricConfig validates symmetric configuration values. +func obrimKeyValidateSymmetricConfig(config map[string]any) map[string]any { + if len(config) != 2 { + return obrimKeyBuildError("FAILED_INVALID_CONFIGURATION") + } + + for key := range config { + if key != "algorithm" && key != "key_size" { + return obrimKeyBuildError("FAILED_UNSUPPORTED_CONFIGURATION_FIELD") + } + } + + algorithmValue, exists := config["algorithm"] + if !exists { + return obrimKeyBuildError("FAILED_ALGORITHM_REQUIRED") + } + + algorithm, ok := algorithmValue.(string) + if !ok { + return obrimKeyBuildError("FAILED_INVALID_ALGORITHM") + } + + normalizedConfig := obrimKeyNormalizeSymmetricConfig(config) + + if strings.ToLower(strings.TrimSpace(algorithm)) != obrimKeyAlgorithmAES { + return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM") + } + + keySizeValue, exists := normalizedConfig["key_size"] + if !exists { + return obrimKeyBuildError("FAILED_KEY_SIZE_REQUIRED") + } + + keySize, ok := keySizeValue.(int) + if !ok { + return obrimKeyBuildError("FAILED_INVALID_KEY_SIZE") + } + + if keySize != 128 && keySize != 192 && keySize != 256 { + return obrimKeyBuildError("FAILED_UNSUPPORTED_KEY_SIZE") + } + + return nil +} + +// obrimKeyValidateAsymmetricConfig validates asymmetric configuration values. +func obrimKeyValidateAsymmetricConfig(config map[string]any) map[string]any { + if len(config) != 1 { + return obrimKeyBuildError("FAILED_INVALID_CONFIGURATION") + } + + for key := range config { + if key != "algorithm" { + return obrimKeyBuildError("FAILED_UNSUPPORTED_CONFIGURATION_FIELD") + } + } + + algorithmValue, exists := config["algorithm"] + if !exists { + return obrimKeyBuildError("FAILED_ALGORITHM_REQUIRED") + } + + algorithm, ok := algorithmValue.(string) + if !ok { + return obrimKeyBuildError("FAILED_INVALID_ALGORITHM") + } + + if strings.ToLower(strings.TrimSpace(algorithm)) != obrimKeyAlgorithmECC { + return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM") + } + + return nil +} + +// obrimKeyGenerateSymmetric generates symmetric key material. +func obrimKeyGenerateSymmetric(config map[string]any) map[string]any { + log.ObrimLog("INIT", "Generating symmetric key material.") + + normalizedConfig := obrimKeyNormalizeSymmetricConfig(config) + + payload, err := obrimKeyGenerateAES(normalizedConfig) + if err != nil { + log.ObrimLog("ERROR", err.Error()) + return obrimKeyBuildError("FAILED_KEY_GENERATION") + } + + log.ObrimLog("SUCCESS", "Symmetric key material generated.") + status.ObrimStatus("SUCCESS", "Key generation completed.") + + return map[string]any{ + "status": true, + "code": "SUCCESS_KEY_GENERATED", + "payload": payload, + } +} + +// obrimKeyGenerateAES generates AES key material. +func obrimKeyGenerateAES(config map[string]any) (map[string]any, error) { + // Mutable variable holding key size. + keySize := config["key_size"].(int) + + // Mutable variable holding key bytes. + keyBytes := make([]byte, keySize/8) + + if _, err := rand.Read(keyBytes); err != nil { + return nil, err + } + + if _, err := aes.NewCipher(keyBytes); err != nil { + return nil, err + } + + payload := map[string]any{ + "type": obrimKeyTypeSymmetric, + "algorithm": obrimKeyAlgorithmAES, + "key_size": keySize, + "key_material": base64.StdEncoding.EncodeToString(keyBytes), + "generated_at": time.Now().UTC().Format(time.RFC3339), + } + + return payload, nil +} + +// obrimKeyNormalizeSymmetricConfig normalizes symmetric configuration values. +func obrimKeyNormalizeSymmetricConfig(config map[string]any) map[string]any { + normalized := map[string]any{} + + if value, exists := config["algorithm"]; exists { + if algorithm, ok := value.(string); ok { + normalized["algorithm"] = strings.ToLower(strings.TrimSpace(algorithm)) + } + } + + if value, exists := config["key_size"]; exists { + switch typed := value.(type) { + case int: + normalized["key_size"] = typed + case int8: + normalized["key_size"] = int(typed) + case int16: + normalized["key_size"] = int(typed) + case int32: + normalized["key_size"] = int(typed) + case int64: + normalized["key_size"] = int(typed) + case float32: + normalized["key_size"] = int(typed) + case float64: + normalized["key_size"] = int(typed) + } + } + + return normalized +} + +// obrimKeyGenerateAsymmetric generates asymmetric key material. +func obrimKeyGenerateAsymmetric(config map[string]any) map[string]any { + log.ObrimLog("INIT", "Generating asymmetric key material.") + + normalizedConfig := obrimKeyNormalizeAsymmetricConfig(config) + + payload, err := obrimKeyGenerateECC(normalizedConfig) + if err != nil { + log.ObrimLog("ERROR", err.Error()) + return obrimKeyBuildError("FAILED_KEY_GENERATION") + } + + log.ObrimLog("SUCCESS", "Asymmetric key material generated.") + status.ObrimStatus("SUCCESS", "Key generation completed.") + + return map[string]any{ + "status": true, + "code": "SUCCESS_KEY_GENERATED", + "payload": payload, + } +} + +// obrimKeyGenerateECC generates ECC key pair material. +func obrimKeyGenerateECC(config map[string]any) (map[string]any, error) { + publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + return nil, err + } + + payload := map[string]any{ + "type": obrimKeyTypeAsymmetric, + "algorithm": obrimKeyAlgorithmECC, + "curve": obrimKeyCurveEdDSA, + "public_key": base64.StdEncoding.EncodeToString(publicKey), + "private_key": base64.StdEncoding.EncodeToString(privateKey), + "generated_at": time.Now().UTC().Format(time.RFC3339), + } + + return payload, nil +} + +// obrimKeyNormalizeAsymmetricConfig normalizes asymmetric configuration values. +func obrimKeyNormalizeAsymmetricConfig(config map[string]any) map[string]any { + normalized := map[string]any{} + + if value, exists := config["algorithm"]; exists { + if algorithm, ok := value.(string); ok { + normalized["algorithm"] = strings.ToLower(strings.TrimSpace(algorithm)) + } + } + + return normalized +} + +// obrimKeyBuildPayload constructs standardized success payloads. +func obrimKeyBuildPayload(payload map[string]any) map[string]any { + return map[string]any{ + "status": true, + "code": "SUCCESS", + "payload": payload, + } +} + +// obrimKeyBuildError constructs standardized error responses. +func obrimKeyBuildError(code string) map[string]any { + log.ObrimLog("ERROR", fmt.Sprintf("Key generation failed: %s", code)) + status.ObrimStatus("ERROR", code) + + return map[string]any{ + "status": false, + "code": code, + "payload": nil, + } +} diff --git a/essential/visible/service/helper/log/log.go b/essential/visible/service/helper/log/log.go index e69de29..2935454 100644 --- a/essential/visible/service/helper/log/log.go +++ b/essential/visible/service/helper/log/log.go @@ -0,0 +1,259 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Log +| +| Purpose: +| - Provide framework-level structured plaintext logging with +| deterministic timestamping and persistent platform-aware storage. +| +| Guideline: +| - Use for framework and software logging. +| - Writes append-only UTF-8 log entries. +| - Preserves existing log content. +| - Uses application metadata to determine storage location. +| - Does not implement rotation, retention, archival, or compression. +| +| Example: +| - ObrimLog("SERVICE/FEATURE", "Operation completed.") +| - ObrimLog("HELPER/LOG", "Log initialized.") +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package log + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "time" + + "go/module/essential/visible/service/helper/retriever" +) + +// ObrimLog writes a structured log entry. +func ObrimLog(label string, message string) { + applicationName := obrimLogApplicationResolve() + + timestamp := obrimLogTimestampGenerate() + + entry := obrimLogEntryBuild( + timestamp, + label, + message, + ) + + logDirectory := obrimLogDirectoryResolve(applicationName) + + logFile := obrimLogFileResolve( + logDirectory, + applicationName, + ) + + if !obrimLogFileEnsure(logDirectory, logFile) { + return + } + + obrimLogWrite(logFile, entry) +} + +// obrimLogTimestampGenerate generates deterministic timestamps. +func obrimLogTimestampGenerate() string { + return time.Now().UTC().Format(time.RFC3339) +} + +// obrimLogEntryBuild constructs formatted log entries. +func obrimLogEntryBuild( + timestamp string, + label string, + message string, +) string { + return fmt.Sprintf( + "[%s] [%s] %s\n", + timestamp, + label, + message, + ) +} + +// obrimLogApplicationResolve resolves the application name. +func obrimLogApplicationResolve() string { + value := retriever.ObrimRetriever( + "json", + map[string]any{ + "resource": "application/metadata", + "path": "application.lower", + }, + ) + + name := strings.TrimSpace(fmt.Sprintf("%v", value)) + + if name == "" { + return "application" + } + + return name +} + +// obrimLogDirectoryResolve resolves platform-specific log directory paths. +func obrimLogDirectoryResolve(applicationName string) string { + switch runtime.GOOS { + case "windows": + return obrimLogDirectoryResolveWindows(applicationName) + + case "darwin": + return obrimLogDirectoryResolveMacOS(applicationName) + + default: + return obrimLogDirectoryResolveLinux(applicationName) + } +} + +// obrimLogDirectoryResolveLinux resolves Linux log directory paths. +func obrimLogDirectoryResolveLinux(applicationName string) string { + xdgStateHome := strings.TrimSpace(os.Getenv("XDG_STATE_HOME")) + + if xdgStateHome != "" { + return filepath.Join( + xdgStateHome, + "."+applicationName, + "logs", + ) + } + + homeDirectory, errorValue := os.UserHomeDir() + + if errorValue != nil { + return filepath.Join( + ".", + "."+applicationName, + "logs", + ) + } + + return filepath.Join( + homeDirectory, + ".local", + "state", + "."+applicationName, + "logs", + ) +} + +// obrimLogDirectoryResolveWindows resolves Windows log directory paths. +func obrimLogDirectoryResolveWindows(applicationName string) string { + localApplicationData := strings.TrimSpace( + os.Getenv("LOCALAPPDATA"), + ) + + if localApplicationData == "" { + homeDirectory, errorValue := os.UserHomeDir() + + if errorValue == nil { + localApplicationData = homeDirectory + } + } + + return filepath.Join( + localApplicationData, + applicationName, + "Logs", + ) +} + +// obrimLogDirectoryResolveMacOS resolves macOS log directory paths. +func obrimLogDirectoryResolveMacOS(applicationName string) string { + homeDirectory, errorValue := os.UserHomeDir() + + if errorValue != nil { + return filepath.Join( + ".", + "."+applicationName, + ) + } + + return filepath.Join( + homeDirectory, + "Library", + "Logs", + "."+applicationName, + ) +} + +// obrimLogFileResolve resolves platform-specific log file paths. +func obrimLogFileResolve( + logDirectory string, + applicationName string, +) string { + return filepath.Join( + logDirectory, + applicationName+".log", + ) +} + +// obrimLogFileEnsure creates and verifies required log directories and files. +func obrimLogFileEnsure( + logDirectory string, + logFile string, +) bool { + errorValue := os.MkdirAll( + logDirectory, + 0755, + ) + + if errorValue != nil { + return false + } + + fileHandle, errorValue := os.OpenFile( + logFile, + os.O_CREATE, + 0644, + ) + + if errorValue != nil { + return false + } + + _ = fileHandle.Close() + + return true +} + +// obrimLogWrite persists log entries to the filesystem. +func obrimLogWrite( + logFile string, + entry string, +) { + fileHandle, errorValue := os.OpenFile( + logFile, + os.O_CREATE|os.O_WRONLY|os.O_APPEND, + 0644, + ) + + if errorValue != nil { + return + } + + defer fileHandle.Close() + + _, _ = fileHandle.WriteString(entry) +} diff --git a/essential/visible/service/helper/marker/marker.go b/essential/visible/service/helper/marker/marker.go index e69de29..ba0369e 100644 --- a/essential/visible/service/helper/marker/marker.go +++ b/essential/visible/service/helper/marker/marker.go @@ -0,0 +1,500 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Marker +| +| Purpose: +| - Provide a unified utility for generating unique markers through +| time-based, random, and encoded generation strategies. +| +| Guideline: +| - Use ObrimMarker as the single entry point. +| - Validate marker type before processing. +| - Maintain standardized response structures. +| - Use isolated workflows for each marker type. +| - Support future marker extensions without modifying existing workflows. +| +| Example: +| - ObrimMarker("time", map[string]any{}) +| - ObrimMarker("random", map[string]any{"length":16}) +| - ObrimMarker("encoded", map[string]any{"data":"example"}) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package marker + +import ( + "crypto/rand" + "crypto/sha256" + "encoding/base64" + "encoding/binary" + "fmt" + "math" + "strings" + "time" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/status" +) + +const ( + obrimMarkerTypeTime = "time" + obrimMarkerTypeRandom = "random" + obrimMarkerTypeEncoded = "encoded" + + obrimMarkerDefaultEpoch int64 = 0 + obrimMarkerDefaultLength = 16 + + obrimMarkerDefaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +) + +// ObrimMarker routes marker generation requests and returns a standardized marker response. +func ObrimMarker(markerType string, config map[string]any) map[string]any { + log.ObrimLog("INIT", "Marker utility initialized.") + status.ObrimStatus("INFO", "Processing marker generation request.") + + if !obrimMarkerValidateType(markerType) { + log.ObrimLog("ERROR", "Unsupported marker type.") + status.ObrimStatus("ERROR", "Unsupported marker type.") + + return obrimMarkerBuildResponse( + false, + "FAILED_UNSUPPORTED_TYPE", + nil, + ) + } + + response := obrimMarkerRoute(markerType, config) + + if statusValue, ok := response["status"].(bool); ok && statusValue { + log.ObrimLog("SUCCESS", "Marker generated successfully.") + status.ObrimStatus("SUCCESS", "Marker generated successfully.") + } else { + log.ObrimLog("ERROR", "Marker generation failed.") + status.ObrimStatus("ERROR", "Marker generation failed.") + } + + return response +} + +// obrimMarkerValidateType validates supported marker generation types. +func obrimMarkerValidateType(markerType string) bool { + switch markerType { + case obrimMarkerTypeTime, + obrimMarkerTypeRandom, + obrimMarkerTypeEncoded: + return true + default: + return false + } +} + +// obrimMarkerRoute routes execution to the selected marker generation workflow. +func obrimMarkerRoute(markerType string, config map[string]any) map[string]any { + switch markerType { + case obrimMarkerTypeTime: + return obrimMarkerTime(config) + + case obrimMarkerTypeRandom: + return obrimMarkerRandom(config) + + case obrimMarkerTypeEncoded: + return obrimMarkerEncoded(config) + + default: + return obrimMarkerBuildResponse( + false, + "FAILED_UNSUPPORTED_TYPE", + nil, + ) + } +} + +// obrimMarkerBuildResponse builds standardized success and error responses. +func obrimMarkerBuildResponse( + statusValue bool, + code string, + payload any, +) map[string]any { + return map[string]any{ + "status": statusValue, + "code": code, + "payload": payload, + } +} + +// obrimMarkerTime generates time-based unique markers. +func obrimMarkerTime(config map[string]any) map[string]any { + if err := obrimMarkerValidateTime(config); err != nil { + return obrimMarkerBuildResponse( + false, + "FAILED_VALIDATION", + nil, + ) + } + + // Mutable variable storing effective epoch. + var epoch int64 = obrimMarkerDefaultEpoch + + if value, ok := config["epoch"]; ok { + switch typed := value.(type) { + case int64: + epoch = typed + case int: + epoch = int64(typed) + case float64: + epoch = int64(typed) + } + } + + // Mutable variable storing instance identifier. + var instance string + + if value, ok := config["instance"].(string); ok { + instance = value + } + + marker, err := obrimMarkerTimeGenerate(epoch, instance) + if err != nil { + return obrimMarkerBuildResponse( + false, + "FAILED_GENERATION", + nil, + ) + } + + payload := map[string]any{ + "marker": marker, + "epoch": epoch, + "instance": instance, + } + + return obrimMarkerBuildResponse( + true, + "SUCCESS_TIME_GENERATED", + payload, + ) +} + +// obrimMarkerValidateTime validates time marker configuration parameters. +func obrimMarkerValidateTime(config map[string]any) error { + if value, ok := config["epoch"]; ok { + switch typed := value.(type) { + case int64: + if typed < 0 { + return fmt.Errorf("invalid epoch") + } + case int: + if typed < 0 { + return fmt.Errorf("invalid epoch") + } + case float64: + if typed < 0 { + return fmt.Errorf("invalid epoch") + } + default: + return fmt.Errorf("invalid epoch type") + } + } + + if value, ok := config["instance"]; ok { + instance, valid := value.(string) + if !valid || strings.TrimSpace(instance) == "" { + return fmt.Errorf("invalid instance") + } + } + + return nil +} + +// obrimMarkerTimeGenerate produces the final time-based marker value. +func obrimMarkerTimeGenerate(epoch int64, instance string) (string, error) { + // Mutable variable storing current timestamp. + var currentTimestamp int64 = time.Now().UnixMilli() + + // Mutable variable storing relative timestamp. + var relativeTimestamp int64 = currentTimestamp - epoch + + if relativeTimestamp < 0 { + return "", fmt.Errorf("invalid timestamp") + } + + source := fmt.Sprintf("%d:%s", relativeTimestamp, instance) + + hash := sha256.Sum256([]byte(source)) + + return strings.ToUpper(base64.RawURLEncoding.EncodeToString(hash[:])), nil +} + +// obrimMarkerRandom generates random collision-resistant markers. +func obrimMarkerRandom(config map[string]any) map[string]any { + if err := obrimMarkerValidateRandom(config); err != nil { + return obrimMarkerBuildResponse( + false, + "FAILED_VALIDATION", + nil, + ) + } + + // Mutable variable storing desired length. + var length int = obrimMarkerDefaultLength + + if value, ok := config["length"]; ok { + switch typed := value.(type) { + case int: + length = typed + case int64: + length = int(typed) + case float64: + length = int(typed) + } + } + + // Mutable variable storing charset. + var charset string = obrimMarkerDefaultCharset + + if value, ok := config["charset"].(string); ok { + charset = value + } + + marker, err := obrimMarkerRandomGenerate(length, charset) + if err != nil { + return obrimMarkerBuildResponse( + false, + "FAILED_GENERATION", + nil, + ) + } + + payload := map[string]any{ + "marker": marker, + "length": length, + "charset": charset, + } + + return obrimMarkerBuildResponse( + true, + "SUCCESS_RANDOM_GENERATED", + payload, + ) +} + +// obrimMarkerValidateRandom validates random marker configuration parameters. +func obrimMarkerValidateRandom(config map[string]any) error { + if value, ok := config["length"]; ok { + switch typed := value.(type) { + case int: + if typed <= 0 { + return fmt.Errorf("invalid length") + } + case int64: + if typed <= 0 { + return fmt.Errorf("invalid length") + } + case float64: + if typed <= 0 { + return fmt.Errorf("invalid length") + } + default: + return fmt.Errorf("invalid length type") + } + } + + if value, ok := config["charset"]; ok { + charset, valid := value.(string) + + if !valid || len(charset) == 0 { + return fmt.Errorf("invalid charset") + } + } + + return nil +} + +// obrimMarkerRandomGenerate produces the final random marker value. +func obrimMarkerRandomGenerate(length int, charset string) (string, error) { + // Mutable variable storing generated marker bytes. + var markerBuilder strings.Builder + + charsetLength := len(charset) + + for index := 0; index < length; index++ { + randomIndex, err := obrimMarkerRandomIndex(charsetLength) + if err != nil { + return "", err + } + + markerBuilder.WriteByte(charset[randomIndex]) + } + + return markerBuilder.String(), nil +} + +// obrimMarkerRandomIndex generates a secure random index. +func obrimMarkerRandomIndex(limit int) (int, error) { + randomBytes := make([]byte, 8) + + if _, err := rand.Read(randomBytes); err != nil { + return 0, err + } + + randomValue := binary.BigEndian.Uint64(randomBytes) + + return int(randomValue % uint64(limit)), nil +} + +// obrimMarkerEncoded generates deterministic encoded markers. +func obrimMarkerEncoded(config map[string]any) map[string]any { + if err := obrimMarkerValidateEncoded(config); err != nil { + return obrimMarkerBuildResponse( + false, + "FAILED_VALIDATION", + nil, + ) + } + + source := config["data"].(string) + + // Mutable variable storing desired length. + var length int = obrimMarkerDefaultLength + + if value, ok := config["length"]; ok { + switch typed := value.(type) { + case int: + length = typed + case int64: + length = int(typed) + case float64: + length = int(typed) + } + } + + // Mutable variable storing charset. + var charset string = obrimMarkerDefaultCharset + + if value, ok := config["charset"].(string); ok { + charset = value + } + + // Mutable variable storing optional salt. + var salt string + + if value, ok := config["salt"].(string); ok { + salt = value + } + + marker, err := obrimMarkerEncodedGenerate( + source, + length, + charset, + salt, + ) + + if err != nil { + return obrimMarkerBuildResponse( + false, + "FAILED_GENERATION", + nil, + ) + } + + payload := map[string]any{ + "marker": marker, + "source": source, + "length": length, + } + + return obrimMarkerBuildResponse( + true, + "SUCCESS_ENCODED_GENERATED", + payload, + ) +} + +// obrimMarkerValidateEncoded validates encoded marker configuration parameters. +func obrimMarkerValidateEncoded(config map[string]any) error { + data, ok := config["data"].(string) + + if !ok || strings.TrimSpace(data) == "" { + return fmt.Errorf("invalid data") + } + + if value, ok := config["length"]; ok { + switch typed := value.(type) { + case int: + if typed <= 0 { + return fmt.Errorf("invalid length") + } + case int64: + if typed <= 0 { + return fmt.Errorf("invalid length") + } + case float64: + if typed <= 0 { + return fmt.Errorf("invalid length") + } + default: + return fmt.Errorf("invalid length type") + } + } + + if value, ok := config["charset"]; ok { + charset, valid := value.(string) + + if !valid || len(charset) == 0 { + return fmt.Errorf("invalid charset") + } + } + + return nil +} + +// obrimMarkerEncodedGenerate produces the final encoded marker value. +func obrimMarkerEncodedGenerate( + source string, + length int, + charset string, + salt string, +) (string, error) { + hash := sha256.Sum256([]byte(source + salt)) + + charsetLength := len(charset) + + if charsetLength == 0 { + return "", fmt.Errorf("invalid charset") + } + + // Mutable variable storing generated marker bytes. + var markerBuilder strings.Builder + + for _, value := range hash { + index := int(math.Abs(float64(value))) % charsetLength + markerBuilder.WriteByte(charset[index]) + + if markerBuilder.Len() >= length { + break + } + } + + for markerBuilder.Len() < length { + markerBuilder.WriteByte(charset[0]) + } + + return markerBuilder.String(), nil +} diff --git a/essential/visible/service/helper/progress/progress.go b/essential/visible/service/helper/progress/progress.go index e69de29..347d59f 100644 --- a/essential/visible/service/helper/progress/progress.go +++ b/essential/visible/service/helper/progress/progress.go @@ -0,0 +1,443 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Progress +| +| Purpose: +| - Manage, monitor, and report task progress through standardized +| lifecycle-aware progress tracking. +| +| Guideline: +| - Use countable progress when current and target values are available. +| - Use uncountable progress when only activity status is available. +| - Always provide a valid lifecycle state. +| - Use standardized response structures for all executions. +| +| Example: +| - ObrimProgress("countable", map[string]any{ +| "state":"running", +| "current":25, +| "target":100, +| }) +| +| - ObrimProgress("uncountable", map[string]any{ +| "state":"running", +| "placeholder":"Synchronizing resources", +| }) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package progress + +import ( + "fmt" + "math" + "strings" + "sync" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/status" +) + +const ( + obrimProgressTypeCountable = "countable" + obrimProgressTypeUncountable = "uncountable" + + obrimProgressStateStarted = "started" + obrimProgressStateRunning = "running" + obrimProgressStateCompleted = "completed" + obrimProgressStateCanceled = "canceled" + + obrimProgressVisualWidth = 20 +) + +var ( + // obrimProgressStateMutex protects lifecycle transitions. + obrimProgressStateMutex sync.Mutex +) + +// ObrimProgress manages lifecycle-aware countable and uncountable progress tracking operations. +func ObrimProgress(progressType string, config map[string]any) map[string]any { + obrimProgressStateMutex.Lock() + defer obrimProgressStateMutex.Unlock() + + if !obrimProgressValidate(progressType, config) { + return obrimProgressBuildResponse( + false, + "FAILED_PROGRESS_MISCONFIGURED", + nil, + ) + } + + // lifecycleState stores validated lifecycle state. + lifecycleState := strings.ToLower(fmt.Sprintf("%v", config["state"])) + + if !obrimProgressHandleState(lifecycleState) { + return obrimProgressBuildResponse( + false, + "FAILED_PROGRESS_MISCONFIGURED", + nil, + ) + } + + switch progressType { + case obrimProgressTypeCountable: + return obrimProgressCountable(config) + + case obrimProgressTypeUncountable: + return obrimProgressUncountable(config) + + default: + return obrimProgressBuildResponse( + false, + "FAILED_PROGRESS_MISCONFIGURED", + nil, + ) + } +} + +// obrimProgressValidate validates input parameters and configuration consistency. +func obrimProgressValidate(progressType string, config map[string]any) bool { + if strings.TrimSpace(progressType) == "" { + log.ObrimLog("ERROR", "Progress type is missing.") + status.ObrimStatus("ERROR", "Progress type is required.") + return false + } + + if config == nil { + log.ObrimLog("ERROR", "Progress configuration is missing.") + status.ObrimStatus("ERROR", "Progress configuration is required.") + return false + } + + // lifecycleState stores lifecycle state. + lifecycleState := strings.ToLower(fmt.Sprintf("%v", config["state"])) + + switch lifecycleState { + case obrimProgressStateStarted, + obrimProgressStateRunning, + obrimProgressStateCompleted, + obrimProgressStateCanceled: + default: + log.ObrimLog("ERROR", "Invalid progress lifecycle state.") + status.ObrimStatus("ERROR", "Invalid progress lifecycle state.") + return false + } + + switch progressType { + case obrimProgressTypeCountable: + _, currentExists := config["current"] + _, targetExists := config["target"] + + if !currentExists || !targetExists { + return false + } + + // targetValue stores target progress value. + targetValue, ok := obrimProgressConvertToInt(config["target"]) + if !ok || targetValue <= 0 { + return false + } + + case obrimProgressTypeUncountable: + placeholder, ok := config["placeholder"].(string) + if !ok || strings.TrimSpace(placeholder) == "" { + return false + } + + default: + return false + } + + return true +} + +// obrimProgressHandleState processes lifecycle state transitions. +func obrimProgressHandleState(state string) bool { + switch state { + case obrimProgressStateStarted: + log.ObrimLog("INIT", "Progress tracking started.") + status.ObrimStatus("INFO", "Progress started.") + return true + + case obrimProgressStateRunning: + log.ObrimLog("PROGRESS", "Progress tracking updated.") + status.ObrimStatus("INFO", "Progress running.") + return true + + case obrimProgressStateCompleted: + log.ObrimLog("SUCCESS", "Progress tracking completed.") + status.ObrimStatus("SUCCESS", "Progress completed.") + return true + + case obrimProgressStateCanceled: + log.ObrimLog("WARNING", "Progress tracking canceled.") + status.ObrimStatus("WARNING", "Progress canceled.") + return true + } + + return false +} + +// obrimProgressCountable processes countable progress tracking workflows. +func obrimProgressCountable(config map[string]any) map[string]any { + // lifecycleState stores lifecycle state. + lifecycleState := strings.ToLower(fmt.Sprintf("%v", config["state"])) + + // currentValue stores current progress value. + currentValue, _ := obrimProgressConvertToInt(config["current"]) + + // targetValue stores target progress value. + targetValue, _ := obrimProgressConvertToInt(config["target"]) + + // percentage stores normalized completion percentage. + percentage := obrimProgressCalculatePercentage( + currentValue, + targetValue, + ) + + // progressMessage stores human readable progress message. + progressMessage := obrimProgressGenerateMessage( + obrimProgressTypeCountable, + lifecycleState, + percentage, + "", + ) + + // progressVisual stores visual progress representation. + progressVisual := obrimProgressGenerateVisual( + obrimProgressTypeCountable, + percentage, + "", + ) + + payload := map[string]any{ + "state": lifecycleState, + "current": currentValue, + "target": targetValue, + "percentage": percentage, + "message": progressMessage, + "visual": progressVisual, + } + + return obrimProgressBuildResponse( + true, + "SUCCESS_PROGRESS_TRACKED", + payload, + ) +} + +// obrimProgressCalculatePercentage calculates and normalizes completion percentages. +func obrimProgressCalculatePercentage(current int, target int) int { + if target <= 0 { + return 0 + } + + if current < 0 { + return 0 + } + + percentage := int( + math.Round( + (float64(current) / float64(target)) * 100, + ), + ) + + if percentage > 100 { + return 100 + } + + if percentage < 0 { + return 0 + } + + return percentage +} + +// obrimProgressUncountable processes uncountable progress tracking workflows. +func obrimProgressUncountable(config map[string]any) map[string]any { + // lifecycleState stores lifecycle state. + lifecycleState := strings.ToLower(fmt.Sprintf("%v", config["state"])) + + // placeholder stores resolved placeholder text. + placeholder := obrimProgressResolvePlaceholder(config) + + // progressMessage stores human readable progress message. + progressMessage := obrimProgressGenerateMessage( + obrimProgressTypeUncountable, + lifecycleState, + 0, + placeholder, + ) + + // progressVisual stores visual progress representation. + progressVisual := obrimProgressGenerateVisual( + obrimProgressTypeUncountable, + 0, + placeholder, + ) + + payload := map[string]any{ + "state": lifecycleState, + "placeholder": placeholder, + "message": progressMessage, + "visual": progressVisual, + } + + return obrimProgressBuildResponse( + true, + "SUCCESS_PROGRESS_TRACKED", + payload, + ) +} + +// obrimProgressResolvePlaceholder validates and prepares placeholder activity messages. +func obrimProgressResolvePlaceholder(config map[string]any) string { + placeholder, ok := config["placeholder"].(string) + if !ok { + return "" + } + + return strings.TrimSpace(placeholder) +} + +// obrimProgressGenerateMessage generates human-readable progress messages. +func obrimProgressGenerateMessage( + progressType string, + state string, + percentage int, + placeholder string, +) string { + if progressType == obrimProgressTypeCountable { + switch state { + case obrimProgressStateStarted: + return fmt.Sprintf("Progress started (%d%%).", percentage) + + case obrimProgressStateRunning: + return fmt.Sprintf("Progress running (%d%% complete).", percentage) + + case obrimProgressStateCompleted: + return "Progress completed successfully." + + case obrimProgressStateCanceled: + return "Progress canceled." + } + } + + switch state { + case obrimProgressStateStarted: + return fmt.Sprintf("Activity started: %s.", placeholder) + + case obrimProgressStateRunning: + return fmt.Sprintf("Activity running: %s.", placeholder) + + case obrimProgressStateCompleted: + return fmt.Sprintf("Activity completed: %s.", placeholder) + + case obrimProgressStateCanceled: + return fmt.Sprintf("Activity canceled: %s.", placeholder) + } + + return "" +} + +// obrimProgressGenerateVisual generates CLI-friendly visual progress representations. +func obrimProgressGenerateVisual( + progressType string, + percentage int, + placeholder string, +) string { + if progressType == obrimProgressTypeCountable { + filled := int( + math.Round( + (float64(percentage) / 100) * obrimProgressVisualWidth, + ), + ) + + if filled > obrimProgressVisualWidth { + filled = obrimProgressVisualWidth + } + + if filled < 0 { + filled = 0 + } + + return fmt.Sprintf( + "[%s%s] %d%%", + strings.Repeat("#", filled), + strings.Repeat("-", obrimProgressVisualWidth-filled), + percentage, + ) + } + + return fmt.Sprintf("[~] %s", placeholder) +} + +// obrimProgressBuildResponse constructs standardized utility response payloads. +func obrimProgressBuildResponse( + success bool, + code string, + payload map[string]any, +) map[string]any { + if !success { + return map[string]any{ + "status": false, + "code": code, + "payload": nil, + } + } + + return map[string]any{ + "status": true, + "code": code, + "payload": payload, + } +} + +// obrimProgressConvertToInt safely converts supported numeric values to int. +func obrimProgressConvertToInt(value any) (int, bool) { + switch v := value.(type) { + case int: + return v, true + case int8: + return int(v), true + case int16: + return int(v), true + case int32: + return int(v), true + case int64: + return int(v), true + case uint: + return int(v), true + case uint8: + return int(v), true + case uint16: + return int(v), true + case uint32: + return int(v), true + case uint64: + return int(v), true + case float32: + return int(v), true + case float64: + return int(v), true + default: + return 0, false + } +} diff --git a/essential/visible/service/helper/retriever/retriever.go b/essential/visible/service/helper/retriever/retriever.go index e69de29..13e0ab0 100644 --- a/essential/visible/service/helper/retriever/retriever.go +++ b/essential/visible/service/helper/retriever/retriever.go @@ -0,0 +1,323 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Retriever +| +| Purpose: +| - Retrieve data from supported resource providers through a unified +| retrieval interface. +| +| Guideline: +| - Use registered providers to retrieve resources. +| - Use resource identifiers to resolve providers. +| - Use path or fields selection for partial retrieval. +| - Path and fields are mutually exclusive. +| +| Example: +| - ObrimRetriever("json", map[string]any{"resource": "metadata"}) +| - ObrimRetriever("json", map[string]any{ +| "resource": "metadata", +| "path": "application.name", +| }) +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package retriever + +import ( + "fmt" + "strings" + + "go/module/essential/visible/service/helper/log" + "go/module/essential/visible/service/helper/status" +) + +// ObrimRetrieverResponse represents the standardized utility response. +type ObrimRetrieverResponse struct { + Status bool `json:"status"` + Code string `json:"code"` + Payload any `json:"payload"` +} + +// ObrimRetrieverJsonProviderRegistry stores registered JSON providers. +var ObrimRetrieverJsonProviderRegistry = map[string]any{} + +// ObrimRetrieverDbProviderRegistry stores registered database providers. +var ObrimRetrieverDbProviderRegistry = map[string]any{} + +// ObrimRetriever retrieves data using a unified retrieval interface. +func ObrimRetriever(retrievalType string, config map[string]any) map[string]any { + status.ObrimStatus("INFO", "Retriever started.") + log.ObrimLog("INIT", "Retriever execution started.") + + if !obrimRetrieverValidateType(retrievalType) { + return obrimRetrieverBuildResponse(false, "FAILED_UNSUPPORTED_TYPE", nil) + } + + if !obrimRetrieverValidateConfig(retrievalType, config) { + return obrimRetrieverBuildResponse(false, "FAILED_INVALID_CONFIGURATION", nil) + } + + switch retrievalType { + case "json": + return obrimRetrieverJson(config) + + case "db": + return obrimRetrieverDb(config) + + default: + return obrimRetrieverBuildResponse(false, "FAILED_UNSUPPORTED_TYPE", nil) + } +} + +// ObrimRetrieverJsonRegister registers a JSON provider. +func ObrimRetrieverJsonRegister(resource string, provider any) { + ObrimRetrieverJsonProviderRegistry[resource] = provider +} + +// ObrimRetrieverDbRegister registers a database provider. +func ObrimRetrieverDbRegister(resource string, provider any) { + ObrimRetrieverDbProviderRegistry[resource] = provider +} + +// obrimRetrieverValidateType validates the requested retrieval type. +func obrimRetrieverValidateType(retrievalType string) bool { + switch retrievalType { + case "json", "db": + return true + default: + return false + } +} + +// obrimRetrieverValidateConfig validates configuration by retrieval type. +func obrimRetrieverValidateConfig(retrievalType string, config map[string]any) bool { + switch retrievalType { + case "json": + return obrimRetrieverJsonValidate(config) + + case "db": + return obrimRetrieverDbValidate(config) + + default: + return false + } +} + +// obrimRetrieverResolveProvider resolves a provider by resource identifier. +func obrimRetrieverResolveProvider( + retrievalType string, + resource string, +) (any, bool) { + switch retrievalType { + case "json": + provider, exists := ObrimRetrieverJsonProviderRegistry[resource] + return provider, exists + + case "db": + provider, exists := ObrimRetrieverDbProviderRegistry[resource] + return provider, exists + + default: + return nil, false + } +} + +// obrimRetrieverBuildResponse builds a standardized response. +func obrimRetrieverBuildResponse( + success bool, + code string, + payload any, +) map[string]any { + return map[string]any{ + "status": success, + "code": code, + "payload": payload, + } +} + +// obrimRetrieverJson processes JSON retrieval requests. +func obrimRetrieverJson(config map[string]any) map[string]any { + resource, _ := config["resource"].(string) + + provider, exists := obrimRetrieverResolveProvider("json", resource) + if !exists { + return obrimRetrieverBuildResponse(false, "FAILED_RESOURCE_NOT_FOUND", nil) + } + + data, err := obrimRetrieverJsonResource(provider) + if err != nil { + return obrimRetrieverBuildResponse(false, "FAILED_RESOURCE_NOT_FOUND", nil) + } + + _, hasPath := config["path"] + _, hasFields := config["fields"] + + if hasPath { + return obrimRetrieverJsonPath(data, config) + } + + if hasFields { + return obrimRetrieverJsonFields(data, config) + } + + return obrimRetrieverBuildResponse( + true, + "SUCCESS_RESOURCE", + map[string]any{ + "data": data, + }, + ) +} + +// obrimRetrieverJsonResource retrieves a complete resource payload. +func obrimRetrieverJsonResource(provider any) (any, error) { + switch value := provider.(type) { + case func() (any, error): + return value() + + case func() any: + return value(), nil + + default: + return nil, fmt.Errorf("invalid provider") + } +} + +// obrimRetrieverJsonPath retrieves a value using dot notation. +func obrimRetrieverJsonPath( + data any, + config map[string]any, +) map[string]any { + path, _ := config["path"].(string) + + value, found := obrimRetrieverResolvePath(data, path) + if !found { + return obrimRetrieverBuildResponse(false, "FAILED_PATH_NOT_FOUND", nil) + } + + return obrimRetrieverBuildResponse( + true, + "SUCCESS_PATH", + map[string]any{ + "data": value, + }, + ) +} + +// obrimRetrieverJsonFields retrieves multiple values using field selection. +func obrimRetrieverJsonFields( + data any, + config map[string]any, +) map[string]any { + fields, ok := config["fields"].([]string) + if !ok { + rawFields, castOk := config["fields"].([]any) + if !castOk { + return obrimRetrieverBuildResponse(false, "FAILED_INVALID_CONFIGURATION", nil) + } + + fields = make([]string, 0, len(rawFields)) + + for _, field := range rawFields { + fieldString, stringOk := field.(string) + if !stringOk { + return obrimRetrieverBuildResponse(false, "FAILED_INVALID_CONFIGURATION", nil) + } + + fields = append(fields, fieldString) + } + } + + result := map[string]any{} + + for _, field := range fields { + value, found := obrimRetrieverResolvePath(data, field) + if !found { + return obrimRetrieverBuildResponse(false, "FAILED_FIELD_NOT_FOUND", nil) + } + + result[field] = value + } + + return obrimRetrieverBuildResponse( + true, + "SUCCESS_FIELDS", + map[string]any{ + "data": result, + }, + ) +} + +// obrimRetrieverJsonValidate validates JSON configuration. +func obrimRetrieverJsonValidate(config map[string]any) bool { + resource, exists := config["resource"] + if !exists { + return false + } + + resourceString, ok := resource.(string) + if !ok || strings.TrimSpace(resourceString) == "" { + return false + } + + _, hasPath := config["path"] + _, hasFields := config["fields"] + + if hasPath && hasFields { + return false + } + + return true +} + +// obrimRetrieverDb processes database retrieval requests. +func obrimRetrieverDb(config map[string]any) map[string]any { + return obrimRetrieverBuildResponse(false, "FAILED_NOT_IMPLEMENTED", nil) +} + +// obrimRetrieverDbValidate validates database configuration. +func obrimRetrieverDbValidate(config map[string]any) bool { + return true +} + +// obrimRetrieverResolvePath resolves a dot-notation path. +func obrimRetrieverResolvePath(data any, path string) (any, bool) { + if strings.TrimSpace(path) == "" { + return nil, false + } + + current := data + + for _, segment := range strings.Split(path, ".") { + object, ok := current.(map[string]any) + if !ok { + return nil, false + } + + value, exists := object[segment] + if !exists { + return nil, false + } + + current = value + } + + return current, true +} diff --git a/essential/visible/service/helper/status/status.go b/essential/visible/service/helper/status/status.go index e69de29..a9b3bf4 100644 --- a/essential/visible/service/helper/status/status.go +++ b/essential/visible/service/helper/status/status.go @@ -0,0 +1,108 @@ +/* +|-------------------------------------------------------------------------- +| Manifest +|-------------------------------------------------------------------------- +| +| Name: +| - Status +| +| Purpose: +| - Provide a framework-level CLI status utility that standardizes +| terminal message presentation using semantic labels and visual +| indicators to ensure consistent output across all applications. +| +| Guideline: +| - Use semantic labels to classify terminal messages. +| - Invalid, unsupported, or empty labels default to INFO. +| - Emits exactly one terminal message per invocation. +| - Intended for framework and software level terminal messaging. +| +| Example: +| - ObrimStatus("INFO", "Application started.") +| - ObrimStatus("SUCCESS", "Operation completed.") +| - ObrimStatus("WARNING", "Configuration missing.") +| - ObrimStatus("ERROR", "Operation failed.") +| +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Credit +|-------------------------------------------------------------------------- +| +| Contributor: +| - Rajon Ahmed +| - Scionite +| +|-------------------------------------------------------------------------- +*/ + +package status + +import ( + "fmt" + "strings" +) + +// ObrimStatus emits a standardized CLI status message. +func ObrimStatus(label string, message string) { + normalizedLabel := obrimStatusNormalizeLabel(label) + formattedLabel := obrimStatusFormatLabel(normalizedLabel) + indicator := obrimStatusFormatIndicator(normalizedLabel) + finalMessage := obrimStatusBuildMessage( + formattedLabel, + indicator, + message, + ) + + fmt.Println(finalMessage) +} + +// obrimStatusNormalizeLabel normalizes and validates status labels. +func obrimStatusNormalizeLabel(label string) string { + normalizedLabel := strings.ToUpper(strings.TrimSpace(label)) + + switch normalizedLabel { + case "INFO": + return "INFO" + case "WARNING": + return "WARNING" + case "SUCCESS": + return "SUCCESS" + case "ERROR": + return "ERROR" + default: + return "INFO" + } +} + +// obrimStatusFormatLabel formats semantic status labels. +func obrimStatusFormatLabel(label string) string { + return "[" + label + "]" +} + +// obrimStatusFormatIndicator generates visual status indicators. +func obrimStatusFormatIndicator(label string) string { + switch label { + case "INFO": + return "ℹ" + case "WARNING": + return "⚠" + case "SUCCESS": + return "✓" + case "ERROR": + return "✖" + default: + return "ℹ" + } +} + +// obrimStatusBuildMessage constructs the final terminal message. +func obrimStatusBuildMessage( + label string, + indicator string, + message string, +) string { + return fmt.Sprintf("%s %s %s", indicator, label, message) +}