Host-object bindings¶
An editor, scene application, or automation host usually keeps its own document format. When that document refers to PostProject knowledge, persist the complete production-scoped identity rather than an object UUID by itself:
https://postproject.org/ref/v1/<production UUID>/<object kind>/<object UUID>
The supported object-kind tokens are production, asset, representation,
resource, and activity. Treat the serialized value as opaque identity text.
Its project-controlled HTTPS namespace can point to documentation, but parsing
and using a binding never performs a network request.
Formatting and parsing are pure value operations available in every library surface. The example binds a representation, stores the text, and parses it back:
static pp_error_code_t bind_representation(const pp_uuid_t *production_id,
const pp_uuid_t *representation_id,
pp_error_t **error) {
const pp_object_ref_t object = {PP_OBJECT_REPRESENTATION,
*representation_id};
char *stored = NULL;
pp_uuid_t parsed_production = {{0}};
pp_object_ref_t parsed_object = {0, {{0}}};
pp_error_code_t status =
pp_host_binding_format(production_id, &object, &stored, error);
if (status == PP_OK) {
printf("binding: %s\n", stored);
status = pp_host_binding_parse(stored, &parsed_production, &parsed_object,
error);
}
if (status == PP_OK &&
(memcmp(&parsed_production, production_id, sizeof *production_id) != 0 ||
parsed_object.kind != object.kind ||
memcmp(&parsed_object.id, &object.id, sizeof object.id) != 0)) {
status = PP_ERROR_INTERNAL;
}
pp_host_binding_release(stored);
return status;
}
std::string bind_representation(const postproject::Production &production,
const postproject::Uuid &representation_id) {
const postproject::HostObjectBinding binding{
production.id(), {postproject::ObjectKind::representation,
representation_id}};
const std::string stored = binding.toString();
const auto reopened = postproject::HostObjectBinding::fromString(stored);
require(reopened == binding, "binding round trip");
return stored;
}
def bind_representation(
production: Production, representation_id: RepresentationId
) -> str:
stored = production.host_bindings[representation_id]
binding = production.host_bindings.parse(stored)
assert binding.production_id == production.id
assert binding.object == representation_id
return stored
fn bind_representation(
production_id: ProductionId,
representation_id: RepresentationId,
) -> Result<String> {
let binding =
HostObjectBinding::new(production_id, ObjectRef::Representation(representation_id))?;
let stored = binding.to_string();
let reopened = HostObjectBinding::from_str(&stored)?;
assert_eq!(reopened, binding);
Ok(stored)
}
The CLI does not format or parse host-object bindings. Use one of the library surfaces.
A formatted C string is caller-owned and must be released exactly once with
pp_host_binding_release; parsed UUID and object-reference values are copied
into caller-owned output structs. The other surfaces return ordinary values.
Parsing is deliberately strict: versions and object kinds must be known, UUIDs must use lowercase hyphenated canonical text, and extra fields are rejected. A future format can therefore be introduced without interpreting ambiguous old text. The former development-only private-scheme spelling is not accepted.
Fallback information¶
A host may separately retain a display name, production path, or last known locator to help a person repair an unavailable binding. That fallback is never part of identity. If the production cannot be opened or the object does not exist, preserve the binding and report an explicit rebind state; do not silently select a production or object from fallback text.
The opposite direction¶
When PostProject needs to find an object owned by the host, attach the host’s stable identifier through the external-identifier API. Host identifiers are lookup aids and assertions. They do not become globally unique merely because a host supplied them, and they do not replace the production-scoped binding above.