 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			121 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| hackme
 | |
| ======
 | |
| 
 | |
| Design rational are documented here.
 | |
| 
 | |
| This doc is not necessary reading for users of this package,
 | |
| but if you're considering submitting patches -- or just trying to understand
 | |
| why it was written this way, and check for reasoning that might be dated --
 | |
| then it might be useful reading.
 | |
| 
 | |
| It may also be an incomplete doc.  It's been written opportunistically.
 | |
| If you don't understand the rationale for some things, try checking git history
 | |
| (many of the commit messages are downright bookish), or get in touch via
 | |
| a github issue, irc, matrix, etc and ask!
 | |
| 
 | |
| 
 | |
| about NodeAssembler and NodeBuilder
 | |
| -----------------------------------
 | |
| 
 | |
| See the godoc on these types.
 | |
| 
 | |
| In short, a `NodeBuilder` is for creating a new piece of memory;
 | |
| a `NodeAssembler` is for instantiating some memory which you already have.
 | |
| 
 | |
| Generally, you'll start any function using a `NodeBuilder`, but then continue
 | |
| and recurse by passing on the `NodeAssembler`.
 | |
| 
 | |
| See the `./HACKME_builderBehaviors.md` doc for more details on
 | |
| high level rules and implementation patterns to look out for.
 | |
| 
 | |
| 
 | |
| 
 | |
| about NodePrototype
 | |
| ---------------
 | |
| 
 | |
| ### NodePrototype promises information without allocations
 | |
| 
 | |
| You'll notice nearly every `ipld.NodePrototype` implementation is
 | |
| a golang struct type with _zero fields_.
 | |
| 
 | |
| This is important.
 | |
| Getting a NodePrototype is generally expected to be "free" (i.e., zero allocations),
 | |
| while `NewBuilder` is allowed to be costly (usually causes at least one allocation).
 | |
| Zero-member structs can be referred to by an interface without requiring an allocation,
 | |
| which is how it's possible ensure `NodePrototype` are always "free" to refer to.
 | |
| 
 | |
| (Note that a `NodePrototype` that bundles some information like ADL configuration
 | |
| will subvert this pattern -- but these are an exception, not the rule.)
 | |
| 
 | |
| ### NodePrototype reported by a Node
 | |
| 
 | |
| `ipld.NodePrototype` is a type that opaquely represents some information about how
 | |
| a node was constructed and is implemented.  The general contract for what
 | |
| should happen when asking a node about its prototype
 | |
| (via the `ipld.Node.Prototype() NodePrototype` interface) is that prototype should contain
 | |
| effective instructions for how one could build a copy of that node, using
 | |
| the same implementation details.
 | |
| 
 | |
| By example, if some node `n` was made as a `basicnode.plainString`,
 | |
| then `n.Prototype()` will be `basicnode.Prototype.String`,
 | |
| and `n.Prototype().NewBuilder().AssignString("xyz")` can be presumed to work.
 | |
| 
 | |
| Note there are also limits to this: if a node was built in a flexible way,
 | |
| the prototype it reports later may only report what it is now, and not return
 | |
| that same flexibility again.
 | |
| By example, if something was made as an "any" -- i.e.,
 | |
| via `basicnode.Prototype.Any.NewBuilder()`, and then *happened* to be assigned a string value --
 | |
| the resulting node will still carry a `Prototype()` property that returns
 | |
| `basicnode.Prototype.String` -- **not** `basicnode.Prototype.Any`.
 | |
| 
 | |
| #### NodePrototype meets generic transformation
 | |
| 
 | |
| One of the core purposes of the `NodePrototype` interface (and all the different
 | |
| ways you can get it from existing data) is to enable the `traversal` package
 | |
| (or other user-written packages like it) to do transformations on data.
 | |
| 
 | |
| // work-in-progress warning: generic transformations are not fully implemented.
 | |
| 
 | |
| When implementating a transformation that works over unknown data,
 | |
| the signiture of function a user provides is roughly:
 | |
| `func(oldValue Node, acceptableValues NodePrototype) (Node, error)`.
 | |
| (This signiture may vary by the strategy taken by the transformation -- this
 | |
| signiture is useful because it's capable of no-op'ing; an alternative signiture
 | |
| might give the user a `NodeAssembler` instead of the `NodePrototype`.)
 | |
| 
 | |
| In this situation, the transformation system determines the `NodePrototype`
 | |
| (or `NodeAssembler`) to use by asking the parent value of the one we're visiting.
 | |
| This is because we want to give the update function the ability to create
 | |
| any kind of value that would be accepted in this position -- not just create a
 | |
| value of the same prototype as the one currently there!  It is for this reason
 | |
| the `oldValue.Prototype()` property can't be used directly.
 | |
| 
 | |
| At the root of such a transformation, we use the `node.Prototype()` property to
 | |
| determine how to get started building a new value.
 | |
| 
 | |
| #### NodePrototype meets recursive assemblers
 | |
| 
 | |
| Asking for a NodePrototype in a recursive assembly process tells you about what
 | |
| kind of node would be accepted in an `AssignNode(Node)` call.
 | |
| It does *not* make any remark on the fact it's a key assembler or value assembler
 | |
| and might be wrapped with additional rules (such as map key uniqueness, field
 | |
| name expectations, etc).
 | |
| 
 | |
| (Note that it's also not an exclusive statement about what `AssignNode(Node)` will
 | |
| accept; e.g. in many situations, while a `Prototype.MyStringType` might be the prototype
 | |
| returned, any string kinded node can be used in `AssignNode(Node)` and will be
 | |
| appropriately converted.)
 | |
| 
 | |
| Any of these paths counts as "recursive assembly process":
 | |
| 
 | |
| - `MapAssembler.KeyPrototype()`
 | |
| - `MapAssembler.ValuePrototype(string)`
 | |
| - `MapAssembler.AssembleKey().Prototype()`
 | |
| - `MapAssembler.AssembleValue().Prototype()`
 | |
| - `ListAssembler.ValuePrototype()`
 | |
| - `ListAssembler.AssembleValue().Prototype()`
 | |
| 
 | |
| ### NodePrototype for carrying ADL configuration
 | |
| 
 | |
| // work-in-progress warning: this is an intention of the design, but not implemented.
 |