Compare commits

...

10 Commits

Author SHA1 Message Date
José René White Enciso
c82b825420 chore(building-block-catalog): checkpoint pending development updates 2026-03-09 11:57:46 -06:00
José René White Enciso
3eb8107066 chore(repo): normalize ignore policy and repository metadata paths 2026-03-06 08:17:46 -06:00
José René White Enciso
2af2a4a1aa Merge branch 'feature/catalog-stable-package-baseline' into development 2026-02-25 16:50:50 -06:00
José René White Enciso
c7b0bc4061 refactor(building-block-catalog): consume blueprint common via package 2026-02-25 16:17:53 -06:00
José René White Enciso
79889c8b73 chore(building-block-catalog): stabilize package metadata and version baseline 2026-02-25 15:55:37 -06:00
José René White Enciso
a78a00dc82 merge(building-block-catalog): integrate catalog-contracts-package-baseline 2026-02-25 14:41:57 -06:00
José René White Enciso
e2587b4988 docs(building-block-catalog): add nuget publication baseline 2026-02-25 14:09:15 -06:00
José René White Enciso
9ba651b740 chore(building-block-catalog): merge contract integration branch 2026-02-22 04:56:50 -06:00
José René White Enciso
c149695569 feat(contracts): add transport-neutral catalog contracts
- WHY: align catalog contracts with protocol-agnostic integration boundaries
- WHAT: add contract conventions, grpc adapter surfaces, and blueprint descriptor consumption
- RULE: enforce building-block to blueprint dependency direction
2026-02-22 03:28:32 -06:00
José René White Enciso
5ff7d63e41 chore(tasks): untrack local task files
- WHY: keep task lifecycle files local-only per gitignore policy
- WHAT: remove tracked .tasks entries from repository index
- RULE: apply repository workflow task folder behavior
2026-02-22 01:34:56 -06:00
19 changed files with 226 additions and 146 deletions

58
.gitignore vendored
View File

@ -1,53 +1,23 @@
# AgileWebs local orchestration # Repository orchestration folders (local only)
.repo-tasks/
.repo-context/
.tasks/ .tasks/
.agile/ .agile/
# Build artifacts # .NET build outputs
**/[Bb]in/ **/bin/
**/[Oo]bj/ **/obj/
/**/out/
/**/artifacts/
# IDE and editor files
.vs/ .vs/
.idea/ TestResults/
.vscode/ **/TestResults/
*.suo
*.user *.user
*.userosscache *.suo
*.sln.docstates
*.rsuser *.rsuser
*.swp
*.swo
# NuGet # IDE
.idea/
# Package artifacts
*.nupkg *.nupkg
*.snupkg *.snupkg
**/packages/* artifacts/
!**/packages/build/
# Test output
**/TestResults/
*.trx
*.coverage
*.coveragexml
# Logs
*.log
logs/
# Local environment files
.env
.env.*
!.env.example
# Docker
.docker/
**/.docker/
*.pid
docker-compose.override.yml
docker-compose.*.override.yml
# OS files
.DS_Store
Thumbs.db

View File

@ -1,86 +0,0 @@
# Stage 1 Task
## 0. Header
- Task ID: TASK-20260222-001
- Title: Extract catalog contract ownership from legacy adapters
- Status: Planned
- Priority: P1
- Target Repo: building-block-catalog
- Target Branch: feature/building-block-catalog-001
- Related Master Plan: plan/master-stage1-structural-normalization-2026-02-22.md
- Related Mini Plan: plan/building-block-catalog-mini-plan.md
## 1. Goal (What and Why)
### What
- Identify product, tag, tag type, and tag override contract candidates
- Define clean contract ownership for catalog building block
### Why
- Catalog contracts must be reusable without implementation leakage
## 2. Scope
### In Scope
- Ownership split and contract inventory for catalog capability
### Out of Scope
- Furniture implementation migration
## 3. Constraints (Non-Negotiable)
- Stage 1 planning only. No implementation changes.
- Do not modify any file under legacy.
- Do not run repo provisioning or CI generation.
- Follow the approved architecture boundaries and protocol policy.
- Keep identity abstractions inside Thalos repositories.
## 4. Documentation Requirement
- [ ] Capture planning decisions clearly for handoff.
- [ ] Identify documentation and diagram updates expected in later stages.
## 5. Context
- This task derives from plan/building-block-catalog-mini-plan.md.
- This task must remain decision-focused and implementation-ready.
## 6. Proposed Approach
- Define a catalog contract ownership matrix from legacy adapter inputs
## 7. Execution Steps
1. Review legacy evidence relevant to this task scope.
2. Define target boundary decisions and contract implications.
3. Record risks, dependencies, and compatibility notes.
4. Produce clear handoff guidance for implementation stage.
## 8. Acceptance Criteria
- [ ] Decisions are explicit, scoped, and actionable.
- [ ] Ownership boundaries are unambiguous.
- [ ] Protocol policy alignment is explicit where applicable.
- [ ] No forbidden Stage 1 actions were performed.
## 9. Testing Plan
### Unit Tests
- Not applicable for Stage 1 planning artifacts.
### Validation
- Ensure consistency with master plan and mini plan.
## 10. Definition of Done
- [ ] Task content is complete and consistent with other task files.
- [ ] References to master and mini plans are correct.
- [ ] Handoff notes are clear enough for immediate implementation.
## 11. Risks and Questions
- Risk: boundary drift during implementation.
- Mitigation: enforce repo intent metadata and mini plan ownership.
## 12. Handoff Notes
- Preserve approved constraints exactly.
- Implementers should execute this task only after reading master and mini plans.
END OF TASK
## 13. Completion Metadata
- Completion Stage: Stage 3 Execution
- Completed On: 2026-02-22
- Completed By: Codex
- Completion Branch: feature/building-block-catalog-001
- Completion Commit: d45d882
- Lifecycle State: done

10
Directory.Build.props Normal file
View File

@ -0,0 +1,10 @@
<Project>
<PropertyGroup>
<Authors>AgileWebs</Authors>
<Company>AgileWebs</Company>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitea.dream-views.com/AgileWebs/building-block-catalog</RepositoryUrl>
<PackageProjectUrl>https://gitea.dream-views.com/AgileWebs/building-block-catalog</PackageProjectUrl>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
</PropertyGroup>
</Project>

View File

@ -3,16 +3,24 @@ skinparam packageStyle rectangle
package "building-block-catalog" { package "building-block-catalog" {
package "BuildingBlock.Catalog.Contracts" { package "BuildingBlock.Catalog.Contracts" {
class Conventions
class Products class Products
class Tags class Tags
interface Adapters
class Grpc
interface Abstractions interface Abstractions
} }
} }
package "blueprint-platform" {
interface IBlueprintPackageContract
}
package "furniture-dal" as FurnitureDal package "furniture-dal" as FurnitureDal
package "furniture-service" as FurnitureService package "furniture-service" as FurnitureService
package "furniture-bff" as FurnitureBff package "furniture-bff" as FurnitureBff
Conventions ..> IBlueprintPackageContract
FurnitureDal --> Products FurnitureDal --> Products
FurnitureDal --> Tags FurnitureDal --> Tags
FurnitureService --> Products FurnitureService --> Products

View File

@ -6,12 +6,16 @@
## Contract Groups ## Contract Groups
- `Products`: product contract shapes. - `Conventions`: transport-neutral request/response and envelope conventions.
- `Tags`: tag, tag type, and tag override contract shapes. - `Products`: transport-neutral product contract shapes.
- `Tags`: transport-neutral tag, tag type, and tag override contract shapes.
- `Abstractions`: marker abstraction for contract ownership. - `Abstractions`: marker abstraction for contract ownership.
- `Adapters`: protocol adapter boundaries.
- `Grpc`: gRPC contract shapes for adapter translation.
## Ownership Boundary ## Ownership Boundary
- This repository owns reusable catalog capability contracts. - This repository owns reusable catalog capability contracts.
- Persistence and transport concerns remain outside this package. - Contract metadata consumes `Core.Blueprint.Common.Contracts` and does not redefine Blueprint contracts.
- Persistence and transport implementations remain outside this package.
- Identity abstractions remain Thalos-owned. - Identity abstractions remain Thalos-owned.

View File

@ -6,7 +6,12 @@
- Breaking changes require major version increments. - Breaking changes require major version increments.
- Deprecated members remain through one deprecation cycle. - Deprecated members remain through one deprecation cycle.
## Blueprint Compatibility
- Package descriptor metadata is implemented via `IBlueprintPackageContract` from `Core.Blueprint.Common.Contracts`.
- Catalog contracts consume Blueprint common contract primitives rather than redefining them.
## Compatibility Notes ## Compatibility Notes
- Consumers (`furniture-dal`, `furniture-service`, `furniture-bff`) update explicitly. - Consumers (`furniture-dal`, `furniture-service`, `furniture-bff`) update explicitly.
- Transport-specific adapters are out of scope for this contracts package. - Protocol adapters remain edge concerns; catalog contracts remain transport-neutral.

View File

@ -0,0 +1,29 @@
# Catalog Contracts NuGet Publication Baseline
## Feed
- Source: `https://gitea.dream-views.com/api/packages/AgileWebs/nuget/index.json`
- Authentication: Gitea login + token
- HTTP requirement: `allowInsecureConnections="true"` in `nuget.config`
## Stable Version Matrix
| Package | Version | Published On |
| --- | --- | --- |
| BuildingBlock.Catalog.Contracts | 0.2.0 | 2026-02-25 |
## Dependency Note
`BuildingBlock.Catalog.Contracts` depends on:
- `Core.Blueprint.Common` version `0.2.0`
Stable package waves must keep dependency versions aligned.
## Consumer Validation
Restore validation passed using:
- `TargetFramework`: `net10.0`
- `PackageReference`: `BuildingBlock.Catalog.Contracts` `0.2.0`
- Restore flags: `--no-cache --force`

View File

@ -0,0 +1,25 @@
using BuildingBlock.Catalog.Contracts.Grpc;
using BuildingBlock.Catalog.Contracts.Products;
using BuildingBlock.Catalog.Contracts.Responses;
namespace BuildingBlock.Catalog.Contracts.Adapters;
/// <summary>
/// Defines adapter boundary for catalog gRPC contract translation.
/// </summary>
public interface ICatalogGrpcContractAdapter
{
/// <summary>
/// Maps transport-neutral product contract into gRPC shape.
/// </summary>
/// <param name="contract">Transport-neutral product contract.</param>
/// <returns>gRPC product contract shape.</returns>
CatalogProductGrpcContract ToGrpcProduct(ProductContract contract);
/// <summary>
/// Maps gRPC product contract into transport-neutral response.
/// </summary>
/// <param name="contract">gRPC product contract shape.</param>
/// <returns>Transport-neutral product response contract.</returns>
ProductContractResponse FromGrpcProduct(CatalogProductGrpcContract contract);
}

View File

@ -4,4 +4,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Core.Blueprint.Common" Version="0.2.0" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,8 @@
namespace BuildingBlock.Catalog.Contracts.Conventions;
/// <summary>
/// Defines transport-neutral envelope metadata for catalog contract messages.
/// </summary>
/// <param name="ContractVersion">Contract schema version.</param>
/// <param name="CorrelationId">Correlation identifier for cross-service tracing.</param>
public sealed record CatalogContractEnvelope(string ContractVersion, string CorrelationId);

View File

@ -0,0 +1,15 @@
using Core.Blueprint.Common.Contracts;
namespace BuildingBlock.Catalog.Contracts.Conventions;
/// <summary>
/// Defines package descriptor metadata for catalog contracts package.
/// </summary>
public sealed class CatalogPackageContract : IBlueprintPackageContract
{
/// <inheritdoc />
public BlueprintPackageDescriptor Descriptor { get; } = new(
"BuildingBlock.Catalog.Contracts",
PackageVersionPolicy.Minor,
["Core.Blueprint.Common"]);
}

View File

@ -0,0 +1,9 @@
namespace BuildingBlock.Catalog.Contracts.Conventions;
/// <summary>
/// Defines transport-neutral request contract shape for catalog capability operations.
/// </summary>
/// <typeparam name="TResponse">Response contract type.</typeparam>
public interface ICatalogContractRequest<out TResponse>
{
}

View File

@ -0,0 +1,8 @@
namespace BuildingBlock.Catalog.Contracts.Grpc;
/// <summary>
/// Defines minimal gRPC contract shape for catalog product adapter translation.
/// </summary>
/// <param name="ProductId">Product identifier.</param>
/// <param name="DisplayName">Product display name.</param>
public sealed record CatalogProductGrpcContract(string ProductId, string DisplayName);

View File

@ -1,8 +1,15 @@
using BuildingBlock.Catalog.Contracts.Conventions;
namespace BuildingBlock.Catalog.Contracts.Products; namespace BuildingBlock.Catalog.Contracts.Products;
/// <summary> /// <summary>
/// Catalog product contract. /// Transport-neutral catalog product contract.
/// </summary> /// </summary>
/// <param name="Envelope">Contract envelope metadata.</param>
/// <param name="ProductId">Product identifier in catalog capability scope.</param> /// <param name="ProductId">Product identifier in catalog capability scope.</param>
/// <param name="DisplayName">Product display name.</param> /// <param name="DisplayName">Product display name.</param>
public sealed record ProductContract(string ProductId, string DisplayName); public sealed record ProductContract(
CatalogContractEnvelope Envelope,
string ProductId,
string DisplayName)
: ICatalogContractRequest<Responses.ProductContractResponse>;

View File

@ -0,0 +1,14 @@
using BuildingBlock.Catalog.Contracts.Conventions;
namespace BuildingBlock.Catalog.Contracts.Responses;
/// <summary>
/// Transport-neutral catalog product response contract.
/// </summary>
/// <param name="Envelope">Contract envelope metadata.</param>
/// <param name="ProductId">Product identifier in catalog capability scope.</param>
/// <param name="DisplayName">Product display name.</param>
public sealed record ProductContractResponse(
CatalogContractEnvelope Envelope,
string ProductId,
string DisplayName);

View File

@ -1,9 +1,16 @@
using BuildingBlock.Catalog.Contracts.Conventions;
namespace BuildingBlock.Catalog.Contracts.Tags; namespace BuildingBlock.Catalog.Contracts.Tags;
/// <summary> /// <summary>
/// Catalog tag contract. /// Transport-neutral catalog tag contract.
/// </summary> /// </summary>
/// <param name="Envelope">Contract envelope metadata.</param>
/// <param name="TagId">Tag identifier.</param> /// <param name="TagId">Tag identifier.</param>
/// <param name="TagTypeId">Tag type identifier.</param> /// <param name="TagTypeId">Tag type identifier.</param>
/// <param name="Value">Tag value.</param> /// <param name="Value">Tag value.</param>
public sealed record TagContract(string TagId, string TagTypeId, string Value); public sealed record TagContract(
CatalogContractEnvelope Envelope,
string TagId,
string TagTypeId,
string Value);

View File

@ -1,9 +1,16 @@
using BuildingBlock.Catalog.Contracts.Conventions;
namespace BuildingBlock.Catalog.Contracts.Tags; namespace BuildingBlock.Catalog.Contracts.Tags;
/// <summary> /// <summary>
/// Catalog tag override contract for consumer-specific overrides. /// Transport-neutral catalog tag override contract.
/// </summary> /// </summary>
/// <param name="Envelope">Contract envelope metadata.</param>
/// <param name="TagId">Tag identifier.</param> /// <param name="TagId">Tag identifier.</param>
/// <param name="TargetScope">Override target scope.</param> /// <param name="TargetScope">Override target scope.</param>
/// <param name="OverrideValue">Override value.</param> /// <param name="OverrideValue">Override value.</param>
public sealed record TagOverrideContract(string TagId, string TargetScope, string OverrideValue); public sealed record TagOverrideContract(
CatalogContractEnvelope Envelope,
string TagId,
string TargetScope,
string OverrideValue);

View File

@ -1,8 +1,14 @@
using BuildingBlock.Catalog.Contracts.Conventions;
namespace BuildingBlock.Catalog.Contracts.Tags; namespace BuildingBlock.Catalog.Contracts.Tags;
/// <summary> /// <summary>
/// Catalog tag type contract. /// Transport-neutral catalog tag type contract.
/// </summary> /// </summary>
/// <param name="Envelope">Contract envelope metadata.</param>
/// <param name="TagTypeId">Tag type identifier.</param> /// <param name="TagTypeId">Tag type identifier.</param>
/// <param name="Name">Tag type name.</param> /// <param name="Name">Tag type name.</param>
public sealed record TagTypeContract(string TagTypeId, string Name); public sealed record TagTypeContract(
CatalogContractEnvelope Envelope,
string TagTypeId,
string Name);

View File

@ -1,26 +1,57 @@
using BuildingBlock.Catalog.Contracts.Conventions;
using BuildingBlock.Catalog.Contracts.Products; using BuildingBlock.Catalog.Contracts.Products;
using BuildingBlock.Catalog.Contracts.Responses;
using BuildingBlock.Catalog.Contracts.Tags; using BuildingBlock.Catalog.Contracts.Tags;
using Core.Blueprint.Common.Contracts;
namespace BuildingBlock.Catalog.Contracts.UnitTests; namespace BuildingBlock.Catalog.Contracts.UnitTests;
public class ContractShapeTests public class ContractShapeTests
{ {
[Fact] [Fact]
public void ProductContract_WhenCreated_StoresRequiredValues() public void ProductContract_WhenCreated_StoresTransportNeutralValues()
{ {
var contract = new ProductContract("PRD-001", "Chair"); var envelope = new CatalogContractEnvelope("1.0.0", "corr-123");
var contract = new ProductContract(envelope, "PRD-001", "Chair");
Assert.Equal("1.0.0", contract.Envelope.ContractVersion);
Assert.Equal("corr-123", contract.Envelope.CorrelationId);
Assert.Equal("PRD-001", contract.ProductId); Assert.Equal("PRD-001", contract.ProductId);
Assert.Equal("Chair", contract.DisplayName); Assert.Equal("Chair", contract.DisplayName);
} }
[Fact] [Fact]
public void TagOverrideContract_WhenCreated_StoresRequiredValues() public void TagOverrideContract_WhenCreated_StoresTransportNeutralValues()
{ {
var contract = new TagOverrideContract("TAG-001", "furniture", "featured"); var envelope = new CatalogContractEnvelope("1.0.0", "corr-123");
var contract = new TagOverrideContract(envelope, "TAG-001", "furniture", "featured");
Assert.Equal("1.0.0", contract.Envelope.ContractVersion);
Assert.Equal("corr-123", contract.Envelope.CorrelationId);
Assert.Equal("TAG-001", contract.TagId); Assert.Equal("TAG-001", contract.TagId);
Assert.Equal("furniture", contract.TargetScope); Assert.Equal("furniture", contract.TargetScope);
Assert.Equal("featured", contract.OverrideValue); Assert.Equal("featured", contract.OverrideValue);
} }
[Fact]
public void CatalogPackageContract_WhenCreated_UsesBlueprintDescriptorContract()
{
IBlueprintPackageContract contract = new CatalogPackageContract();
Assert.Equal("BuildingBlock.Catalog.Contracts", contract.Descriptor.PackageId);
Assert.Equal(PackageVersionPolicy.Minor, contract.Descriptor.VersionPolicy);
Assert.Contains("Core.Blueprint.Common", contract.Descriptor.DependencyPackageIds);
}
[Fact]
public void ProductContractResponse_WhenCreated_StoresTransportNeutralValues()
{
var envelope = new CatalogContractEnvelope("1.0.0", "corr-456");
var response = new ProductContractResponse(envelope, "PRD-001", "Chair");
Assert.Equal("1.0.0", response.Envelope.ContractVersion);
Assert.Equal("corr-456", response.Envelope.CorrelationId);
Assert.Equal("PRD-001", response.ProductId);
Assert.Equal("Chair", response.DisplayName);
}
} }