Feature Platform — Developer Guide
Feature Platform — Developer Guide
Section titled “Feature Platform — Developer Guide”How to build a new extension (feature) and add it to the catalog. For the platform overview and runtime behavior, see Feature Platform.
OSS vs Marketplace extensions
Section titled “OSS vs Marketplace extensions”An extension is an independent CloudFormation stack that an admin installs into
the same account as the main IDP stack. There are two kinds, distinguished by
the catalog source field:
OSS (source: oss) | Marketplace (source: marketplace) (future) | |
|---|---|---|
| Status | available today | framework only — no Marketplace extensions exist yet |
| Audience | bundled with the open-source accelerator | closed-source, sold via AWS Marketplace |
| Where the template lives | the stack-owned FeatureBucket (published with the accelerator’s own artifacts) | a private seller bucket you control (GetObject-only) |
| Catalog entry | config_library/extensions-oss.yaml (just a path) | config_library/extensions-marketplace.yaml (full metadata) |
| Install gate | none — installable directly | GetEntitlements(productCode) must report an active subscription before the host hands out a presigned template URL |
| UI CTA | Install | Subscribe → then Install |
Marketplace is a future capability. The framework (catalog schema, entitlement check, presigned-template flow) is in place, but no AWS Marketplace extensions are published yet and the path is not exercised in the default deployment. The Marketplace steps below document how it will work so authors can plan ahead.
Authoring the feature itself (manifest + UI bundle + CFN template) is identical for both kinds. Only the catalog registration (the last step) differs. Build and test as an OSS extension first; the Marketplace path layers on entitlement + a private seller bucket later.
1. Scaffold
Section titled “1. Scaffold”pip install -e lib/idp_feature_sdkidp-feature-cli init ./my-feature --feature-id my-feature --display-name "My Feature"This copies feature-platform/feature-template/
and substitutes the featureId / displayName / version placeholders. The
result is a working feature you can iterate on:
my-feature/├── feature.yaml # manifest (featureId, displayName, version, description, …)├── template.yaml # the feature's CloudFormation stack├── feature-api/ # optional backend Lambda + HTTP API├── feature-ui/ # React UMD bundle rendered inside the host UI│ └── src/{entry.tsx, App.tsx}└── ui-deployer/ # custom resource: copies the UI bundle into the host # WebUIBucket and registers the feature on Create/Delete2. Implement the host contract
Section titled “2. Implement the host contract”Three things make a feature work inside the host. The scaffold wires all three; you fill in the behavior.
UI bundle — feature-ui/src/entry.tsx must register the component, and
vite.config.ts must externalise the host’s shared libraries (React, ReactDOM,
Cloudscape, aws-amplify, react-router-dom) so the bundle shares the host’s React
instance:
window.IdpFeatures.register('my-feature', { Component: App, // receives FeatureContext as props version: '0.1.0', // must match feature.yaml -> version displayName: 'My Feature',});The host-side half of this contract is
src/ui/src/components/feature-page/feature-host-globals.ts.
Backend API (optional) — if your feature needs a backend, template.yaml
creates an HTTP API + Lambda and outputs the endpoint. The ui-deployer writes it
to InstalledFeatures.featureApiEndpoint, and the host passes it to your UI as
FeatureContext.featureApiEndpoint. Authorize the API against the main stack’s
Cognito User Pool (Fn::ImportValue: <MainStackName>-UserPoolId); the UI gets a
fresh token via context.getAuthToken().
Registration — template.yaml must include the RegisterFeature custom
resource (provided by the scaffold’s ui-deployer/) that calls the host AppSync
registerFeature mutation on Create/Update and unregisters on Delete. Without
it the feature never appears in the nav.
Validate the manifest against the schema any time:
idp-feature-cli validate ./my-featureidp-feature-cli show-schema # full feature.yaml schema referenceOptional: pipeline hooks
Section titled “Optional: pipeline hooks”A feature can run a Lambda at any of six post-step extension points in the
document-processing workflow — postOcr, postClassification,
postExtraction, postAssessment, postRuleValidation, postSummarization —
to enrich, validate, or react to results mid-pipeline. The host’s
PipelineHooksDispatcherFunction invokes registered hooks after each step; the
mechanism is inert until a feature registers one.
1. Write the hook Lambda. It’s invoked synchronously with:
{ "hookPoint": "postExtraction", "featureId": "my-feature", "document": { ... }, "section": { ... }, "executionArn": "arn:aws:states:..." }Do your work and return any JSON result (surfaced to the workflow under
$.HookResults). The Lambda must be tagged idp:feature-id=<featureId>
(the host’s dispatcher only invokes tagged or GENAIIDP-*-named functions —
the scaffold tags feature Lambdas for you).
2. Declare it in template.yaml + the manifest. Add the hook Lambda to your
feature’s CloudFormation template, then map the hook point to that Lambda’s
logical resource name in feature.yaml:
pipelineHooks: postExtraction: MyExtractionHookFunction # logical resource name in template.yaml3. Register at install (primary path). The feature stack resolves those
logical names to ARNs and calls the host’s registerFeatureHooks mutation on
Create (and clears them on Delete) — the same custom-resource pattern as
registerFeature. The host writes them into the active config version’s
<step>.postHook lists. Each entry is
{ featureId, arn, order (default 100), onError (default continue), enabled };
onError is continue | skip-remaining | fail.
Escape hatch (no feature install). For custom business logic outside the
feature-install flow, an admin can add postHook entries to a config version
directly (same shape as above). The hook Lambda still needs the
idp:feature-id tag or a GENAIIDP-* name to clear the dispatcher’s IAM
check. This is handy for one-off integrations, but installable features should
use registerFeatureHooks so hooks are added/removed with the stack.
See Feature Platform → Pipeline hooks for the full contract.
Optional: ship a configuration preset
Section titled “Optional: ship a configuration preset”A vertical feature often needs a specific accelerator configuration (custom document classes, extraction prompts, rule-validation policy classes, …). A feature can bundle that configuration and apply it at install:
1. Add the preset file and declare it in the manifest.
configPreset: path: config-preset/my-config.yaml # repo-relative; uploaded verbatim by the publisher2. Apply at install. The feature stack’s ui-deployer downloads the preset
and calls the host’s applyFeatureConfigPreset mutation, which writes it as a
new, non-active configuration version named <featureId>-v<version>.
Installation never changes the active configuration — an admin reviews the
preset on the Configuration page and activates it deliberately. On uninstall
the feature calls removeFeatureConfigPreset, which deletes the feature’s
preset versions except one that is currently active (it is preserved so
in-flight documents keep resolving their configuration).
This pairs naturally with pipeline hooks: ship the configuration the vertical needs and the hook that reacts to its results.
Host exports for features that read processing results
Section titled “Host exports for features that read processing results”Features that read pipeline output import these host exports (in addition to
the always-available <MainStackName>-TrackingTableName and
-CustomerManagedEncryptionKeyArn):
| Export | For |
|---|---|
<MainStackName>-OutputBucketName | Reading processed-document results (e.g. consolidated summaries) |
<MainStackName>-WorkingBucketName | Loading the compressed document payload a pipeline hook receives |
<MainStackName>-DiscoveryBucketName | Driving the host’s Rules Discovery flow from a feature UI |
3. Add to the catalog
Section titled “3. Add to the catalog”This is the step that makes the feature discoverable. Choose based on kind.
OSS — add the project directory to
config_library/extensions-oss.yaml:
features: - path: feature-platform/sample-feature - path: feature-platform/my-feature # ← your feature (committed to the repo)idp-cli publish then builds it and emits a source: oss catalog entry
automatically. UI metadata comes from your feature.yaml.
Marketplace — publish the feature artifacts to your private seller bucket
(see step 4), create the AWS Marketplace listing, then add an entry to
config_library/extensions-marketplace.yaml:
features: - featureId: my-feature displayName: "My Feature" description: "One-line description shown in the nav and on the feature page." productCode: "<marketplace-product-code>" # GetEntitlements is keyed on this marketplaceListingUrl: "https://aws.amazon.com/marketplace/pp/<id>" sellerBucket: "<your-private-seller-bucket>" sellerBucketRegion: "us-east-1" latestVersion: "0.1.0" templateKey: "features/my-feature/v0.1.0/template.yaml"The host’s seller-bucket access also requires:
- the seller bucket’s bucket policy grants the host’s feature-platform role
s3:GetObject, and - the host stack’s
SellerBucketObjectArnsparameter includes the seller bucket’s object ARN (arn:aws:s3:::<bucket>/*).
Unadvertised features. A catalog entry only adds a feature to the available-to-install list. A feature deployed directly via CloudFormation self-registers (its
RegisterFeaturecustom resource writes to theInstalledFeaturestable) and appears in the Extensions nav once installed — no catalog entry needed. Use this for private/internal features you don’t want surfaced as installable to every admin.
Feature documentation (the “Learn more” link)
Section titled “Feature documentation (the “Learn more” link)”Each feature can expose a Learn more link, shown in its nav hover tooltip
and on its not-yet-installed page. It’s driven by the manifest/catalog
docsUrl field, with a fallback:
- OSS features — write a markdown doc under
docs/extensions/<slug>.mdand setdocsUrl: extensions/<slug>infeature.yaml.make docs-deploypublishesdocs/extensions/*.mdto the Extensions section of the docs site, and the UI resolves the slug to that published page. (The bundled Demo Extension is the worked example:docs/extensions/sample-document-status.md,docsUrl: extensions/sample-document-status.) An absolutehttps://…URL also works. - Marketplace features — closed-source docs aren’t in this repo’s docs
site, so omit
docsUrland the UI uses yourmarketplaceListingUrl(the AWS Marketplace listing already hosts usage instructions). If you’d rather link to your own hosted docs, set an absolutedocsUrlinextensions-marketplace.yaml.
4. Build & publish artifacts
Section titled “4. Build & publish artifacts”idp-feature-cli build ./my-feature # CFN + Lambda + UMD bundle into dist/idp-feature-cli publish ./my-feature \ # upload + update latest.json + Launch URL --feature-bucket <bucket> --region us-east-1- OSS: artifacts ride along with the accelerator’s normal
idp-cli publish; the catalog is regenerated and deployed into the host’s ConfigurationBucket on the next stack create/update. - Marketplace: publish to your private seller bucket, and ensure
templateKey/latestVersionin the catalog entry match what you uploaded.
How the catalog reaches the host: idp-cli publish writes a single
catalog.json (merging both extensions-*.yaml files) under config_library/;
at deploy time it is copied into the stack’s own ConfigurationBucket, and the
host reads it at runtime with one GetObject — no bucket listing, no
artifacts-bucket dependency post-deploy. See
Feature Platform → Catalog & discovery.
5. Local end-to-end test (no real Marketplace)
Section titled “5. Local end-to-end test (no real Marketplace)”Use the standalone marketplace-simulator (shipped separately from the OSS repo) to exercise the Subscribe → Install → Active flow without a real listing:
- Deploy/run the simulator and note its endpoint.
- Publish with simulator registration:
Terminal window idp-feature-cli publish ./my-feature \--feature-bucket <bucket> --region us-east-1 \--register-with-simulator <simulator-endpoint> \--simulator-product-code <product-code> - Deploy the main stack with
EnableFeaturePlatform=trueandFeaturePlatformSimulatorEndpoint=<simulator-endpoint>. - Open the IDP web UI — your feature appears under Extensions.
In the default auto-subscribe mode (no simulator endpoint) OSS features skip the subscription step entirely and go straight to Install.
Reference
Section titled “Reference”- Feature Platform overview
idp_feature_sdkREADME — CLI + library APIfeature-platform/feature-template/— the scaffold you start fromfeature-platform/sample-feature/— minimal reference OSS feature (docs-by-status): UI + API + registration onlyfeature-platform/sample-health-insurance-review/— advanced reference OSS feature (sample-health-insurance-review): adds a config preset, apostRuleValidationpipeline hook, and host-GraphQL calls from the UI (docs)- Manifest schema:
lib/idp_feature_sdk/idp_feature_sdk/schemas/feature-manifest.schema.json(oridp-feature-cli show-schema)