Adds 8 cmdlets for Organization and Sub-Organization CRUD (Get/New/Update/Remove for each), targeting /api/v2/organizations and /api/v1/sub-organizations. Get cmdlets default to List parameter set and switch to Single when -OrganizationId or -SubOrganizationId is supplied. New/Update/Remove honor -WhatIf/-Confirm; Remove defaults to High ConfirmImpact and supports -PassThru. No project context required.
Adds Get-InfisicalSANList: emits a deduplicated SAN candidate set containing the local device name, the device name suffixed with each non-empty DNS suffix found across operational adapters and the system primary domain, every IPv4 unicast address falling within RFC 1918 or CGNAT, and the IPv4/IPv6 loopback addresses. Supports optional case-insensitive -InclusionExpression and -ExclusionExpression regex filters applied in fetch -> include -> exclude -> output order. Output is a single strongly-typed System.String[] array emitted non-enumerated so List<string>.AddRange consumes it directly.
Registers 10 new endpoints, adds InfisicalOrganization/InfisicalSubOrganization models with DTOs, mappers, and clients, full MAML help for all 9 new cmdlets, mapper unit tests, EndpointRegistry inline-data coverage, and docs/DesignSpec.md sections 16.7 and 16.8. build.ps1 CmdletsToExport and Test-ModuleImports expected list now contain 51 cmdlets. README updated with Organization/Sub-Organization tables, the new Get-InfisicalSANList entry, and an end-to-end certificate request example using splatted OrderedDictionary blocks.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.06.2229. Module DLL and manifest embed BuildCommitHash=207e7429e448, matching the source commit they were produced from.
- New cmdlet Start-InfisicalProcess: launches a child process with InfisicalSecret
objects decrypted directly into ProcessStartInfo.Environment (optional -Prefix),
additional -EnvironmentVariables, stdout/stderr capture, -AcceptableExitCodeList,
-ParsingExpression regex parsing, -ExecutionTimeout / -ExecutionTimeoutInterval,
-NoWait, -WindowStyle / -CreateNoWindow parameter sets, -Priority,
-StandardInputObjectList, -SecureArgumentList, -LogOutput, -ContinueOnError, and
ShouldProcess support. Secret plaintext is never written to user or machine scope.
- Stream capture uses event-based OutputDataReceived/ErrorDataReceived with
BeginOutputReadLine/BeginErrorReadLine (no Task / ReadToEndAsync /
GetAwaiter().GetResult()) to avoid PowerShell SynchronizationContext deadlocks.
- Restored the do { log; sleep } while (!HasExited) polling pattern using
Thread.Sleep(pollInterval) so verbose "has been running for X" / "Checking again
in Y" messages fire at the configured cadence even when no -ExecutionTimeout is
supplied.
- TimeSpan values in verbose logs and on the result now use a friendly format
("7 seconds, and 364 milliseconds", "1 minute, and 30 seconds", "N/A" when zero)
matching the legacy Start-ProcessWithOutput GetTimeSpanMessage scriptblock.
- Added DurationFriendly property to InfisicalProcessResult and a "The command
execution took X" verbose line at completion.
- build.ps1 CmdletsToExport and Test-ModuleImports expected list contain 42 cmdlets.
- Added 9 xUnit tests covering FormatFriendly singular/plural, multi-unit joining,
zero, sub-millisecond, and skip-zero-components behavior.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.06.2138. Module DLL and manifest embed BuildCommitHash=318db7048017, matching the source commit they were produced from.
Adds an optional [string] -Prefix parameter that prepends the supplied
string to every emitted variable name, regardless of -Format
(Json/Yaml/Xml/Env/EnvironmentVariables). When omitted or empty the
exporter buffer is forwarded unchanged (no-op).
Implementation clones each InfisicalSecret with SecretName = Prefix +
SecretName so the caller's pipeline objects are never mutated; the
SecureString and Tags/SecretMetadata array references are shared
(read-only usage downstream).
Also updates the cmdlet help XML description + adds a -Prefix example,
and reflects the new parameter in docs/DesignSpec.md.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.05.2040. Module DLL and manifest embed BuildCommitHash=1270c9099cae, matching the source commit they were produced from.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.05.0240. Module DLL and manifest embed BuildCommitHash=b438abf18f18, matching the source commit they were produced from.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.05.0215. Module DLL and manifest embed BuildCommitHash=82f99ea7d4a4, matching the source commit they were produced from.
Search-InfisicalCertificate was a 1:1 duplicate of Get-InfisicalCertificate's
List parameter set after the recent filter-surface expansion (bdec5aa). Both
cmdlets exposed the same ~27 server-side filters and both hit the same
POST /api/v1/projects/{projectId}/certificates/search endpoint. Keeping two
PowerShell cmdlets for the same operation added discovery noise without
benefit.
REMOVED
- src/PSInfisicalAPI/Cmdlets/SearchInfisicalCertificateCmdlet.cs (cmdlet
source, ~140 lines).
- 'Search-InfisicalCertificate' from CmdletsToExport in the source manifest
(Module/PSInfisicalAPI/PSInfisicalAPI.psd1) and from the two generators
in build.ps1 (Write-Manifest cmdlet list + Test-ModuleImports $expectedCmds).
- <command:command> block for Search-InfisicalCertificate from the help XML
(Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml).
- README PKI table row for Search-InfisicalCertificate.
- "For advanced filtering ... use Search-InfisicalCertificate instead"
sentence from the Get-InfisicalCertificate Notes block (no longer true).
RETAINED (internal)
- InfisicalPkiClient.SearchCertificates, InfisicalCertificateSearchQuery,
InfisicalEndpointNames.SearchCertificates and the endpoint registry entry.
Get-InfisicalCertificate and Request-InfisicalCertificate still call them
to walk the search endpoint.
MIGRATION
# Before
Search-InfisicalCertificate -ProjectId $p -Search 'web' -Status 'active'
# After
Get-InfisicalCertificate -ProjectId $p -Search 'web' -Status 'active'
Parameter names, defaults, and paging behavior are identical.
TESTS
- 216/216 passing (one unrelated time-based test in CsrAndRequestCmdletTests
was flaky on the run; passes deterministically when invoked in isolation).
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.05.0205. Module DLL and manifest embed BuildCommitHash=86968c18cb15, matching the source commit they were produced from.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.05.0117. Module DLL and manifest embed BuildCommitHash=cffda99591c9, matching the source commit they were produced from.
BREAKING CHANGES
- Connect-Infisical no longer accepts -ProjectId, -Environment, or -SecretPath.
- InfisicalConnection no longer carries ProjectId, Environment, or DefaultSecretPath.
- Every cmdlet that previously inherited those fields now requires -ProjectId
and/or -Environment as Mandatory=true. -SecretPath / -Path remain optional
and default to "/" at the client layer.
- INFISICAL_PROJECT_ID, INFISICAL_ENVIRONMENT, INFISICAL_SECRET_PATH env-var
scanning removed from Connect-Infisical.
- Resolve{ProjectId,Environment,SecretPath} helpers removed from
InfisicalCmdletBase. ResolveOrganizationId retained.
ADDED
- Get-InfisicalProject -Type <enum> filters the list by product surface
(secret-manager, cert-manager, kms, ssh, secret-scanning, pam, ai) with
IntelliSense via ValidateSet.
- Get-InfisicalProject -IncludeRoles switch maps to includeRoles=true/false
query parameter (always sent).
RATIONALE
- Implicit connection scoping caused 400 Bad Request when the active
connection's ProjectId belonged to a different product surface than the
cmdlet's target (e.g. secret-manager project id passed to /cert-manager/*).
- Explicit parameters make scope unambiguous and make scripts portable
across projects.
- The new -Type filter on Get-InfisicalProject lets callers discover the
correct project id for each subsequent CRUD invocation without needing
connection-level inheritance.
INTERNAL
- All client classes (Secrets / Folders / Environments / Tags / Projects /
Pki) now receive scoping as explicit arguments rather than reading the
InfisicalConnection object.
- Client-layer SecretPath / Path defaulting to "/" is preserved via
FirstNonEmpty(...).
- Help XML updated to remove all "session-pinned" / "active connection"
phrasing; OrderedDictionary splatting examples now include the mandatory
parameters.
- 216/216 unit tests passing.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.04.2335. Module DLL and manifest embed BuildCommitHash=3c39a99b9a4c, matching the source commit they were produced from.
FromEnrollment (new default) consumes an InfisicalCertificateApplicationEnrollment and auto-fills ServerUrl from scep.scepEndpointUrl, CAThumbprint from the RA certificate thumbprint, and mints a fresh dynamic challenge automatically when challengeType=dynamic and -Challenge is not supplied. FromProfile preserves the legacy projection from an InfisicalCertificateProfile but now requires -ApplicationId so the server URL is built against /scep/applications/{appId}/profiles/{profileId}/pkiclient.exe. Manual requires explicit -ServerUrl, -Challenge, and -UniqueId. Module manifest, help XML, and build.ps1 expectedCmds list updated to register the three new cmdlets. CHANGELOG updated.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.04.2147. Module DLL and manifest embed BuildCommitHash=183fb48c32ce, matching the source commit they were produced from.
Adds Get-/Export-/Write-InfisicalScepMdmProfile(ToWmi) to CmdletsToExport in the module manifest and to the build.ps1 manifest template and expected-cmdlet probe. Adds MAML help entries (description, notes, two examples each with an OrderedDictionary splat) for all three cmdlets. Updates README's cmdlet count from 34 to 37 and the cmdlet table with one-line descriptions. CHANGELOG entry summarizes the new feature, the default SCEP URL pattern, the elevation/platform guards, and the export-vs-throw rule for -Force.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.04.2112. Module DLL and manifest embed BuildCommitHash=3754de74f6c8, matching the source commit they were produced from.
New ByProfile parameter set bound by -CertificateProfileId (alias ProfileId) POSTs to /api/v1/cert-manager/certificates with the profile id, the locally generated CSR, and an attributes envelope (subject fields, ttl, notBefore, notAfter, keyUsages, extendedKeyUsages). The wrapped response is unwrapped into the existing InfisicalSignedCertificate so reuse, install, chain-completion and key-protection paths remain unchanged. Issuance that returns without a certificate (e.g. status pending_approval) raises a configuration exception that surfaces the reported status and message. Ttl/NotBefore/NotAfter/KeyUsage/ExtendedKeyUsage parameters are now shared by ByCa and ByProfile. MAML help and existing parameter-set test updated.
List parameter set gains -Kind Internal|Acme|Any. Internal (default) preserves current behavior against /api/v1/cert-manager/ca/internal. Any binds to the generic /api/v1/cert-manager/ca endpoint returning both internal and ACME CAs. Acme uses the generic endpoint and client-side filters to type=acme. ById retrieval is unchanged and still resolves against the internal CA endpoint. The existing InfisicalCertificateAuthority model already exposes a Type property to distinguish entries when -Kind Any is used. MAML help updated.
Covers GET /api/v1/cert-manager/certificate-policies (List default with optional -Limit, -Offset) and GET /api/v1/cert-manager/certificate-policies/{certificatePolicyId} (ById). New InfisicalCertificatePolicy model surfaces subject, SANs, key usages, extended key usages, algorithms, and validity. Polymorphic string-or-array fields (allowed/required/keyAlgorithm) are normalized to arrays; sans is normalized whether the API returns an object or an array. Manifest, build expected list, and MAML help updated.
Covers GET /api/v1/cert-manager/certificate-profiles (List default with optional -Limit, -Offset, -IncludeConfigs) and GET /api/v1/cert-manager/certificate-profiles/{certificateProfileId} (ById). New InfisicalCertificateProfile model surfaces ca/policy ids, slug, enrollment type, per-profile defaults (ttl, key/extended key usages with polymorphic string-or-array shapes flattened) and embedded CA/policy/apiConfig summaries. Manifest, build expected list, and MAML help updated.
Auto-generated by build.ps1 -CommitArtifacts. Build 2026.06.04.1920. Module DLL and manifest embed BuildCommitHash=0f8f44afdb38, matching the source commit they were produced from.
Rebuild outputs only: Module DLL and manifest now embed BuildCommitHash=a34db831d8bf, matching the source commit they were produced from. CHANGELOG gains the 2026.06.04.1917 build stamp. No source changes.
Refreshed Module/PSInfisicalAPI/bin/PSInfisicalAPI.dll and Module/PSInfisicalAPI/PSInfisicalAPI.psd1 so the embedded BuildCommitHash matches the now-checked-in source (was 51bf819, now 2489b7a). CHANGELOG gains the 2026.06.04.1915 build stamp.
README cmdlets section now lists all 34 cmdlets grouped by Session/Secrets/Projects/Environments/Folders/Tags/PKI, each with the synopsis pulled verbatim from Get-Help to keep the two surfaces in sync.
BREAKING: Removed Get-InfisicalProjects, Get-InfisicalEnvironments, Get-InfisicalFolders, Get-InfisicalTags, Get-InfisicalSecrets, and Get-InfisicalCertificates. Their list behavior is now the default parameter set on the singular cmdlets; supplying the identity parameter switches to single-record retrieval. No back-compat aliases.
Fix: SignCertificateBySubscriber endpoint resolved to /api/v1/pki/subscribers/{subscriberName}/sign-certificate (was /pki/pki-subscribers and /cert-manager/pki-subscribers, both 404).
Added Get-InfisicalPkiSubscriber (List/ByName), InfisicalPkiSubscriber model, DTOs, mapper, and InfisicalPkiClient.ListPkiSubscribers/GetPkiSubscriber. MAML help refreshed for all consolidated cmdlets with 2 straight-line + 1 OrderedDictionary splat examples each. README extended with extension guide. CHANGELOG updated. 230/230 tests pass.
Cmdlets added: Request-InfisicalCertificate, Get-InfisicalCertificate, Get-InfisicalCertificates. Request supports BySubscriber/ByCa parameter sets, BouncyCastle CSR generation (RSA/ECDSA/Ed25519), local-key generation, -Install/-InstallChain (chain certs routed to Root vs CertificateAuthority by self-signed status), idempotency reuse with -AllowRenewal/-RenewalThresholdDays, local chain reconstruction with -LocalChainOnly opt-out, Infisical bundle fallback when local stores are incomplete, and private-key protection modes (Exportable/LocalOnly/NonExportable/Ephemeral) via -PrivateKeyProtection plus -PersistKey/-MachineKey/-PrivateKeyPath.
Install-InfisicalCertificate fix: chain certs were previously dumped into CertificateAuthority unconditionally. They are now routed by Subject==Issuer (self-signed -> Root, otherwise -> CertificateAuthority), matching Request-InfisicalCertificate. Routing centralized in InfisicalCertificateRequestHelpers.GetChainCertificateTargetStore and a new InstallChain(IEnumerable<X509Certificate2>,...) overload.
Help: authored Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml covering all 39 cmdlets (synopsis, description, notes, two examples per cmdlet: one-liner + OrderedDictionary splat with preceding Get- resolvers for IDs/slugs).
Build pipeline: build.ps1 stages the help XML into bin/<culture>/ next to the DLL during publish (hard-fails if missing or has zero <command:command> entries). Test-ModuleImports now enumerates every exported cmdlet via Get-Command, cross-checks against expected names, and asserts non-empty synopsis (rejecting auto-generated cmdlet-name fallback), non-empty description, and at least one example with a non-empty <dev:code> block.
Tests: 230/230 passing (up from 190).
Normalizes Hashtable, OrderedDictionary, PSObject-wrapped, and typed generic dictionaries into IDictionary<string,string>[] before parameter binding, enabling native PowerShell @{...} and [ordered]@{...} literals against the strongly-typed -Secrets parameter on New-/Update-InfisicalSecret. Adds 8 transformation tests; 174/174 passing.
- Endpoint registry: register POST/PATCH/DELETE /api/v4/secrets/batch as preferred candidates for BulkCreate/Update/Delete; v3 raw routes retained as automatic fallback.
- DTOs: add projectId (required for v4) alongside workspaceId on the three batch request envelopes; both serialized when set, both ignored when null.
- SecretsClient: populate ProjectId in CreateBatch/UpdateBatch/DeleteBatch so v4 succeeds on first attempt.
- Cmdlets: -Secrets on New/Update-InfisicalSecret changed from Hashtable[] to IDictionary<string,string>[] for stronger typing and tab-completion; converter rewritten to accept IEnumerable<IDictionary<string,string>>. TagIds parsed from comma-separated string; nested Metadata dropped from bulk hashtable surface (still settable programmatically on bulk items).
- Tests: 166 passing (was 161). Bulk endpoints now resolve to v4 primary with v3 fallback; new tests verify projectId envelope serialization, dual-key omission, and TagIds trimming.
- Bulk parameter sets on New-/Update-/Remove-InfisicalSecret via v3/secrets/batch/raw.
- Copy-InfisicalSecret cmdlet wrapping v4/secrets/duplicate.
- InfisicalCmdletBase.Resolve{ProjectId,Environment,SecretPath,ApiVersion,OrganizationId} with verbose inheritance logging.
- All resource cmdlets refactored to use the resolution helpers.
- InfisicalBulkSecretConverter for flexible Hashtable -> DTO mapping.
- 22 new unit tests covering registry, DTOs, converter, and inheritance helpers. Total: 161 passing.
Get-InfisicalSecrets and Get-InfisicalSecret now return real secret values by default. Pass -ViewSecretValue:False to opt in to the server's hidden response. InfisicalSecretMapper detects the <hidden-by-infisical> placeholder and the secretValueHidden flag; in either case SecretValue is set to null instead of pushing the literal placeholder into a SecureString, so downstream auth/export/dictionary consumers can never silently use the placeholder as if it were a real secret.
InfisicalSecret.GetPlainTextValue() returns the SecureString contents as a managed string for ergonomic PowerShell access. ConvertTo-InfisicalSecretDictionary -AsPlainText emits Dictionary<string,string> instead of Dictionary<string,SecureString>; default behavior unchanged. Export-InfisicalSecrets already writes plain text via secret.UsePlainTextValue(), so no switch was added there.
- Endpoint registry now stores ordered candidate lists per logical operation; Get/TryGet preserve prior behavior, new GetCandidates(name) exposes the ladder. Added v3 fallbacks (/api/v3/secrets/raw and /api/v3/secrets/raw/{secretName}) after v4. - InfisicalConnection gains PinnedApiVersion and a ResolvedEndpointVersions cache so the chosen version sticks for the session. - InfisicalSecretsClient.SendWithVersionFallback walks candidates in pin -> cached -> registry order, falls back on routing-style failures (404 without an Infisical JSON envelope, 405, or 400 mentioning workspaceId/projectSlug) when no version is pinned, and surfaces real application errors immediately. - Get-InfisicalSecret(s) expose -ApiVersion; Connect-Infisical sets PinnedApiVersion only when -ApiVersion is explicitly bound on the command line (env-var/default values do not pin). - Logger.Error routes via WriteWarning to avoid premature terminating errors that masked InfisicalApiException details; EnsureSuccess no longer redacts non-2xx bodies so server error envelopes are visible. - InfisicalSecretsClient sends both projectId and workspaceId so it works against both new and legacy server-side validators.
- InfisicalSecretsClient: use projectId / includeImports (camelCase) per Infisical v4 OpenAPI
- Get-InfisicalSecrets / Get-InfisicalSecret: change [bool] flag parameters to [switch]
- DesignSpec.md: updated 14.3 / 14.4 examples to match new switch syntax
- build.ps1: anchor Update-Changelog regex to the literal '## Unreleased' line and limit replacement to 1 to stop exponential duplication of carried-forward markers
- Manifest bumped to 2026.06.03.0032 (commit c866760105)
Scripts:
- Add scripts/Install-GiteaRunner.ps1: cross-platform installer for the
Gitea act_runner daemon (systemd / launchd / Windows Service).
- PowerShell 7+ runtime guard (works under irm | iex).
- Explicit env var resolution (Process -> User -> Machine) for
InstanceUrl and RegistrationToken with named candidates.
- UTF-8 (no BOM) for every file write via [System.IO.File] APIs.
- System proxy + DefaultNetworkCredentials on all web calls.
- Optional -Labels; ServiceName/ServiceDisplayName split prevents
systemd 'Invalid unit name' errors caused by whitespace.
- config.yaml is always generated before the registration skip-check
so upgrades produce a config the daemon can load.
Module:
- InfisicalHttpClient: enable UseDefaultCredentials and attach the
system proxy with DefaultNetworkCredentials so requests work behind
authenticated corporate proxies / SSO.
- ExportInfisicalSecretsCmdlet: make the UTF-8 (no BOM) case explicit
in the encoding resolver.
CI/CD (.gitea/workflows/publish-psgallery.yml):
- Split into build -> release -> publish with hard `needs:` ordering
so publish never runs unless build and release both succeed.
- Build job uploads Module/PSInfisicalAPI as an artifact.
- Release job downloads the artifact, reads the version from the
manifest, zips the module, and creates a Gitea release tagged with
the bare version. Release notes include version, full + short commit
SHA, build timestamp, merged PR info, workflow run link, and any
matching CHANGELOG.md section. Skips cleanly when the tag already
exists.
- Publish job re-validates the downloaded manifest and runs
Publish-Module against PSGallery using PSGALLERY_API_KEY.