Skip to content

v0.3.4

Choose a tag to compare

@ntorga ntorga released this 10 Sep 23:06
· 70 commits to main since this release
55fe44e
feat: add TransientDatabaseService, a shared in-memory SQLite key-value store. Has, Read (ErrKeyNotFound), and Set (upsert) work on a KeyValue model; every instance in the process shares the same data.
feat: add FileClerk.VerifyDirPathRedirectSafety(dirPath, ownerUsernamePtr, ownerUserIdPtr). It walks each directory step without following symlinks. The first problem fails the walk: '..' (ErrDirPathTraversalInvalid), a symlink (ErrSymlinkedPathInvalid), a non-directory (ErrTargetNotDirectory), a foreign owner (ErrDirectoryOwnerInvalid), an unknown account (OwnerLookupFailed), or an uninspectable step (PathCheckFailed). It skips dot and empty components. A numeric UID is compared directly without an account lookup; with no owner given, it expects the process account.
feat: add FileClerk.UpsertFile(settings, content). It holds the verified parent-directory handle open, then creates and swaps the temp file via openat/renameat2. No component is re-resolved after the check, so a swapped path cannot redirect the write. A taken target fails with ErrTargetFileExists unless ShouldOverwrite is set. A symlinked final component is replaced, never followed, unless ShouldFollowSymlinks is set. A symlinked parent chain fails with ErrSymlinkedPathInvalid unless that flag is set. Unset Permissions fails with ErrFilePermissionsInvalid; an invalid final name with ErrFileNameInvalid; an overlong temp name with ErrTempFileNameTooLong. With an owner named, chown runs before chmod. The regex replacers reuse writeFileAtomically but follow symlinks and skip the chain check.
feat: add FileClerk.TempFileNameFactory(targetFileName) and FileClerk.TempFilePathFactory(targetFilePath). They build the hidden `.name.<entropy>.tk-tmp` staging name and path. Both take value objects, and TempFilePathFactory returns (string, error).
refactor: remove FileClerk.RenameFile and FileClerk.DeleteFileContent, one-line aliases of MoveFile and TruncateFileContent.
refactor: replace FileClerk.UpdateFileContent with AppendFileContent(UnixAbsoluteFilePath, content), which only appends. TruncateFileContent now takes a UnixAbsoluteFilePath and calls os.Truncate instead of writing empty content.
refactor: FileClerk.UpsertFile owner is optional. Without one, the chain check expects the process account and chown is skipped, so the file keeps the creating process's ownership. ErrDirectoryOwnerMissing removed.
refactor: PasswordFactory now draws with crypto/rand. Each requested character class occupies its own position, so one guarantee never erases another. CharsetPresenceGuarantor, UsernameFactory, and MailAddressFactory draw with crypto/rand too, so synthesizer.go no longer uses math/rand. A failed crypto/rand draw panics instead of emitting a predictable secret.
refactor: PublicIpAddressResolver orders resolver endpoints with crypto/rand instead of math/rand.Perm.
feat: add Synthesizer.RandomIntegerGenerator(lowestValue, highestValue), which draws a uniform crypto/rand integer between two inclusive bounds. An inverted range panics with RandomIntegerRangeInvalid.
feat: add UserId (*uint32) to ShellSettings. The command runs as that account, UserId 0 included, and Username wins when both are set. An unresolvable target fails unless ShouldIgnoreUsernameLookupError is set; an ignored failure logs ShellTargetAccountUnresolvedRunningAsCurrentAccount. Add ShouldDisableTimeout to remove the execution deadline entirely for runs like day-long backups.
fix: PaginationQueryBuilder resolves ORDER BY fields through the parsed GORM statement schema, so CamelCase input maps to the model's real column. Callers MUST set .Model(...); queries built on .Table(...) alone fail with ParseStatementSchemaError. Unknown fields fail with UnknownPaginationSortFieldError instead of emitting invalid SQL.
fix: PaginationQueryBuilder defaults the last-seen-id cursor column to the schema's primary key instead of the literal id. A model without a primary key fails with ModelWithoutPrimaryKeyError. Both the cursor and ORDER BY columns are quoted through the statement, so neither can inject SQL.
chore: drop github.com/iancoleman/strcase; sort-field mapping now uses GORM's naming strategy.
fix: UnixAbsoluteFilePath and UnixRelativeFilePath no longer treat a dotfile's leading dot as an extension separator; '.hidden' is preserved and '.config.json' yields '.config'.
refactor: extract the page-count rule to PaginationPagesTotalResolver(itemsTotal, itemsPerPage). A partial page counts as a page. Zero page size fails with ErrItemsPerPageCannotBeZero; a page count beyond uint32 fails with ErrPagesTotalOverflow, both checked only in the resolver.
fix: EnvsInspector separates an auto-filled variable from a .env file that lacks a trailing newline.
test: cover UpsertFile, AppendFileContent, VerifyDirPathRedirectSafety, the temp-name factories, PaginationPagesTotalResolver, PasswordFactory class guarantees, schema-resolved sorting, custom primary key cursors, and the ShouldDisableTimeout and UserId shell settings.
test: modernize trailDatabaseService_test.go with t.Setenv, t.Fatalf for critical failures, and extra-model migration coverage through NewTrailDatabaseService instead of the private dbMigrate.
refactor: remove FingerprintSHA1 from X509Certificate (weak hash, go:S4790); FingerprintSHA256 remains. Breaking change to the constructor and the fingerprintSha1 JSON field.
docs: split the component catalog into layer READMEs (domain, infra, presentation) and restructure skills into the OpenCode layout with a new tk-usage skill.