diff --git a/PUBLIC_SOURCE_EXPORT.md b/PUBLIC_SOURCE_EXPORT.md index d56cbc6..e62201b 100644 --- a/PUBLIC_SOURCE_EXPORT.md +++ b/PUBLIC_SOURCE_EXPORT.md @@ -1,3 +1,3 @@ # Public source export -This source snapshot was generated from the private canonical repository at revision `368fba691ea8d23403b4d56b53b5ec670d7c5020`. It contains no private Git history or operational evidence. Changes are published from the canonical repository. +This source snapshot was generated from the private canonical repository at revision `e1fd00a3172eaaec29bf8f1e6e47f96d175c31ff`. It contains no private Git history or operational evidence. Changes are published from the canonical repository. diff --git a/PUBLIC_SOURCE_MANIFEST.json b/PUBLIC_SOURCE_MANIFEST.json index e902218..1604022 100644 --- a/PUBLIC_SOURCE_MANIFEST.json +++ b/PUBLIC_SOURCE_MANIFEST.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "sourceRevision": "368fba691ea8d23403b4d56b53b5ec670d7c5020", + "sourceRevision": "e1fd00a3172eaaec29bf8f1e6e47f96d175c31ff", "files": [ { "path": ".dockerignore", @@ -14,8 +14,8 @@ }, { "path": ".gitleaks.toml", - "sha256": "1e613517e9f602474d7a3377ce4a7c4904cf3b0493331caa2606d6b0f3b05d65", - "bytes": 274 + "sha256": "96206825f15bad4dc958afca88503ba6711eb9f55353c8874157e5052efccd2a", + "bytes": 267 }, { "path": "LICENSE.md", diff --git a/scripts/bootstrap.ps1 b/scripts/bootstrap.ps1 index a76683f..29fcb90 100644 --- a/scripts/bootstrap.ps1 +++ b/scripts/bootstrap.ps1 @@ -1,6 +1,6 @@ -$ErrorActionPreference = "Stop" -Set-Location (Join-Path $PSScriptRoot "..") -python scripts/validate_pack.py -python scripts/next_packet.py -python scripts/render_luna_context.py -Write-Host "`nOpen .luna/context.md and prompts/AUTONOMOUS_BUILD_LUNA.md in Codex." +$ErrorActionPreference = "Stop" +Set-Location (Join-Path $PSScriptRoot "..") +python scripts/validate_pack.py +python scripts/next_packet.py +python scripts/render_luna_context.py +Write-Host "`nOpen .luna/context.md and prompts/AUTONOMOUS_BUILD_LUNA.md in Codex." diff --git a/scripts/install_codex_mcp.ps1 b/scripts/install_codex_mcp.ps1 index 7ec5c60..57b790b 100644 --- a/scripts/install_codex_mcp.ps1 +++ b/scripts/install_codex_mcp.ps1 @@ -1,97 +1,97 @@ -[CmdletBinding()] -param( - [Parameter(Mandatory = $true)] - [ValidatePattern('^[a-z0-9][a-z0-9-]*$')] - [string]$Project, - - [Parameter(Mandatory = $true)] - [ValidatePattern('^[a-z0-9][a-z0-9-]*$')] - [string]$Environment, - - [Parameter(Mandatory = $true)] - [ValidatePattern('^[0-9a-fA-F-]{36}$')] - [string]$HubClientId, - - [Parameter(Mandatory = $true)] - [ValidatePattern('^[a-zA-Z0-9_.@-]+$')] - [string]$OAuthUsername, - - [Parameter(Mandatory = $true)] - [string]$SecretFile, - - [string]$PublicBaseUrl = 'https://mcp.example.com', - [string]$TokenEndpoint = 'https://auth.example-host.com/application/o/token/', - [string]$OAuthClientId = 'itworx-mcp-hub', - [string]$PythonExecutable = '', - [string]$CodexExecutable = '', - [switch]$Force -) - -$ErrorActionPreference = 'Stop' -$repositoryRoot = Split-Path -Parent $PSScriptRoot -$bridge = Join-Path $PSScriptRoot 'mcp_stdio_bridge.py' -$resolvedSecret = (Resolve-Path -LiteralPath $SecretFile).Path -if (-not (Test-Path -LiteralPath $bridge -PathType Leaf)) { - throw 'MCP bridge script is missing.' -} -$secretInfo = Get-Item -LiteralPath $resolvedSecret -if (-not $secretInfo.PSIsContainer -and $secretInfo.Length -gt 0 -and $secretInfo.Length -le 8192) { - # Continue; content is deliberately never read or printed by this installer. -} else { - throw 'Secret file must be a non-empty regular file no larger than 8192 bytes.' -} -if (-not $PublicBaseUrl.StartsWith('https://') -or -not $TokenEndpoint.StartsWith('https://')) { - throw 'Public MCP and OAuth endpoints must use HTTPS.' -} - -if (-not $PythonExecutable) { - $PythonExecutable = (Get-Command python -ErrorAction Stop).Source -} -if (-not $CodexExecutable) { - $CodexExecutable = (Get-Command codex -ErrorAction Stop).Source -} - -$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name -$currentAcl = Get-Acl -LiteralPath $resolvedSecret -if ($currentAcl.Owner -ne $identity) { - throw 'Secret file must already be owned by the current Windows identity.' -} -$verifiedAcl = $currentAcl -$verifiedRules = @($verifiedAcl.Access) -if ( - -not $verifiedAcl.AreAccessRulesProtected -or - $verifiedRules.Count -ne 1 -or - $verifiedRules[0].IdentityReference.Value -ne $identity -or - $verifiedRules[0].AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow -or - ($verifiedRules[0].FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl -) { - throw 'Secret file ACL must grant only the current Windows identity FullControl; use new_codex_credential.ps1.' -} - -$name = "itworx-$Project-$Environment" -$endpoint = "$($PublicBaseUrl.TrimEnd('/'))/mcp/$Project/$Environment" -$existing = & $CodexExecutable mcp get $name 2>$null -if ($LASTEXITCODE -eq 0) { - if (-not $Force) { - throw "Codex MCP server '$name' already exists. Re-run with -Force to replace it." - } - & $CodexExecutable mcp remove $name | Out-Null - if ($LASTEXITCODE -ne 0) { throw "Could not remove existing Codex MCP server '$name'." } -} - -$arguments = @( - 'mcp', 'add', $name, '--', - $PythonExecutable, $bridge, - '--endpoint', $endpoint, - '--client-id', $HubClientId, - '--token-endpoint', $TokenEndpoint, - '--oauth-client-id', $OAuthClientId, - '--oauth-username', $OAuthUsername, - '--client-secret-file', $resolvedSecret, - '--scope', 'openid profile' -) -& $CodexExecutable @arguments | Out-Null -if ($LASTEXITCODE -ne 0) { throw "Could not add Codex MCP server '$name'." } -& $CodexExecutable mcp get $name -if ($LASTEXITCODE -ne 0) { throw "Codex MCP server '$name' was not readable after installation." } -Write-Output "Configured $name for $endpoint. Restart Codex before first use." +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [ValidatePattern('^[a-z0-9][a-z0-9-]*$')] + [string]$Project, + + [Parameter(Mandatory = $true)] + [ValidatePattern('^[a-z0-9][a-z0-9-]*$')] + [string]$Environment, + + [Parameter(Mandatory = $true)] + [ValidatePattern('^[0-9a-fA-F-]{36}$')] + [string]$HubClientId, + + [Parameter(Mandatory = $true)] + [ValidatePattern('^[a-zA-Z0-9_.@-]+$')] + [string]$OAuthUsername, + + [Parameter(Mandatory = $true)] + [string]$SecretFile, + + [string]$PublicBaseUrl = 'https://mcp.example.com', + [string]$TokenEndpoint = 'https://auth.example-host.com/application/o/token/', + [string]$OAuthClientId = 'itworx-mcp-hub', + [string]$PythonExecutable = '', + [string]$CodexExecutable = '', + [switch]$Force +) + +$ErrorActionPreference = 'Stop' +$repositoryRoot = Split-Path -Parent $PSScriptRoot +$bridge = Join-Path $PSScriptRoot 'mcp_stdio_bridge.py' +$resolvedSecret = (Resolve-Path -LiteralPath $SecretFile).Path +if (-not (Test-Path -LiteralPath $bridge -PathType Leaf)) { + throw 'MCP bridge script is missing.' +} +$secretInfo = Get-Item -LiteralPath $resolvedSecret +if (-not $secretInfo.PSIsContainer -and $secretInfo.Length -gt 0 -and $secretInfo.Length -le 8192) { + # Continue; content is deliberately never read or printed by this installer. +} else { + throw 'Secret file must be a non-empty regular file no larger than 8192 bytes.' +} +if (-not $PublicBaseUrl.StartsWith('https://') -or -not $TokenEndpoint.StartsWith('https://')) { + throw 'Public MCP and OAuth endpoints must use HTTPS.' +} + +if (-not $PythonExecutable) { + $PythonExecutable = (Get-Command python -ErrorAction Stop).Source +} +if (-not $CodexExecutable) { + $CodexExecutable = (Get-Command codex -ErrorAction Stop).Source +} + +$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name +$currentAcl = Get-Acl -LiteralPath $resolvedSecret +if ($currentAcl.Owner -ne $identity) { + throw 'Secret file must already be owned by the current Windows identity.' +} +$verifiedAcl = $currentAcl +$verifiedRules = @($verifiedAcl.Access) +if ( + -not $verifiedAcl.AreAccessRulesProtected -or + $verifiedRules.Count -ne 1 -or + $verifiedRules[0].IdentityReference.Value -ne $identity -or + $verifiedRules[0].AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow -or + ($verifiedRules[0].FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl +) { + throw 'Secret file ACL must grant only the current Windows identity FullControl; use new_codex_credential.ps1.' +} + +$name = "itworx-$Project-$Environment" +$endpoint = "$($PublicBaseUrl.TrimEnd('/'))/mcp/$Project/$Environment" +$existing = & $CodexExecutable mcp get $name 2>$null +if ($LASTEXITCODE -eq 0) { + if (-not $Force) { + throw "Codex MCP server '$name' already exists. Re-run with -Force to replace it." + } + & $CodexExecutable mcp remove $name | Out-Null + if ($LASTEXITCODE -ne 0) { throw "Could not remove existing Codex MCP server '$name'." } +} + +$arguments = @( + 'mcp', 'add', $name, '--', + $PythonExecutable, $bridge, + '--endpoint', $endpoint, + '--client-id', $HubClientId, + '--token-endpoint', $TokenEndpoint, + '--oauth-client-id', $OAuthClientId, + '--oauth-username', $OAuthUsername, + '--client-secret-file', $resolvedSecret, + '--scope', 'openid profile' +) +& $CodexExecutable @arguments | Out-Null +if ($LASTEXITCODE -ne 0) { throw "Could not add Codex MCP server '$name'." } +& $CodexExecutable mcp get $name +if ($LASTEXITCODE -ne 0) { throw "Codex MCP server '$name' was not readable after installation." } +Write-Output "Configured $name for $endpoint. Restart Codex before first use." diff --git a/scripts/new_codex_credential.ps1 b/scripts/new_codex_credential.ps1 index e6da783..ccf3df6 100644 --- a/scripts/new_codex_credential.ps1 +++ b/scripts/new_codex_credential.ps1 @@ -1,33 +1,33 @@ -[CmdletBinding()] -param( - [Parameter(Mandatory = $true)] - [ValidatePattern('^[a-z0-9][a-z0-9-]*$')] - [string]$Project, - [string]$OutputDirectory = (Join-Path $env:LOCALAPPDATA 'ITWorx\MCP Hub\credentials'), - [switch]$Rotate -) - -$ErrorActionPreference = 'Stop' -New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null -$path = Join-Path $OutputDirectory "$Project.credential" -if ((Test-Path -LiteralPath $path) -and -not $Rotate) { - throw "Credential already exists at $path. Use -Rotate only for an intentional rotation." -} -$bytes = New-Object byte[] 48 -[System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes) -$value = [Convert]::ToBase64String($bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_') -[System.IO.File]::WriteAllText($path, $value, [System.Text.UTF8Encoding]::new($false)) - -$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name -$acl = New-Object System.Security.AccessControl.FileSecurity -$acl.SetOwner([System.Security.Principal.NTAccount]::new($identity)) -$acl.SetAccessRuleProtection($true, $false) -$acl.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new( - $identity, - [System.Security.AccessControl.FileSystemRights]::FullControl, - [System.Security.AccessControl.AccessControlType]::Allow -)) -Set-Acl -LiteralPath $path -AclObject $acl -[Array]::Clear($bytes, 0, $bytes.Length) -$value = $null -Write-Output $path +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [ValidatePattern('^[a-z0-9][a-z0-9-]*$')] + [string]$Project, + [string]$OutputDirectory = (Join-Path $env:LOCALAPPDATA 'ITWorx\MCP Hub\credentials'), + [switch]$Rotate +) + +$ErrorActionPreference = 'Stop' +New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null +$path = Join-Path $OutputDirectory "$Project.credential" +if ((Test-Path -LiteralPath $path) -and -not $Rotate) { + throw "Credential already exists at $path. Use -Rotate only for an intentional rotation." +} +$bytes = New-Object byte[] 48 +[System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes) +$value = [Convert]::ToBase64String($bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_') +[System.IO.File]::WriteAllText($path, $value, [System.Text.UTF8Encoding]::new($false)) + +$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name +$acl = New-Object System.Security.AccessControl.FileSecurity +$acl.SetOwner([System.Security.Principal.NTAccount]::new($identity)) +$acl.SetAccessRuleProtection($true, $false) +$acl.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new( + $identity, + [System.Security.AccessControl.FileSystemRights]::FullControl, + [System.Security.AccessControl.AccessControlType]::Allow +)) +Set-Acl -LiteralPath $path -AclObject $acl +[Array]::Clear($bytes, 0, $bytes.Length) +$value = $null +Write-Output $path