> For the complete documentation index, see llms.txt.
Skip to main content

Check out Port for yourself ➜ 

Create foundational Engineering Intelligence data model

Included by default

If you signed up for Port on or after May 1, 2026, the Engineering Intelligence data model is already set up in your portal. You can follow this guide to customize it to fit your organization's needs. Learn more about Port's organization hierarchy.

This guide walks you through setting up the foundational data model that powers Port's Engineering Intelligence capabilities.
By the end, you'll have a solid foundation of organizations, teams, services, and repositories all connected through relations, giving you the flexibility to power Port's Engineering Intelligence with visibility at any level from individual services to teams and across the entire organization.

The data model follows a modular architecture: a shared core layer (organization, team, service) plus blueprints created by your integrations. This guide covers GitHub, GitLab, and Azure DevOps, but the core layer is provider-agnostic and stays consistent regardless of which SCM tools you use.

Why this matters

A strong foundational data model is the backbone of engineering intelligence. Well-defined relations between organizations, teams, services, and the tools that support them make it easy to aggregate metrics at the right level, enforce standards through scorecards, and automate workflows across your engineering organization.

How it works

When you connect an SCM integration (GitHub, GitLab, or Azure DevOps), Port automatically generates blueprints for repositories, pull/merge requests, pipelines/workflows, and related objects, then begins ingesting live data into your catalog. Engineering Intelligence properties (DORA metrics, PR throughput, PR cycle time, change failure rate) are calculated directly on those integration entities.

To surface metrics at the service, team, and organization level, create a service and link it to a repository and team. Port then aggregates metrics up the hierarchy from service to team to group to organization, recalculating every 15 minutes.

Common use cases

  • Track DORA metrics across your organization, teams, and services.
  • Enable delivery performance metrics like PR/MR cycle time, throughput, staleness, lead time, and more.
  • Define scorecards at different levels (organization, team, service) and combine them with workflows and automations to enforce engineering standards.
  • Create a unified view of engineering assets across multiple integrations, from SCM and CI/CD to incident management and cloud infrastructure.
  • Power AI agents with structured engineering data for intelligent automation.

Data model overview

The data model has two layers: a provider-agnostic core (Organization, Team, Service) that stays consistent regardless of which tools you use, and integration-specific blueprints created automatically when you connect your SCM and incident management tools.

Each SCM integration ships with blueprints that power different Engineering Intelligence use cases. The tables below show example blueprints used across the EI guides; your integration may ship with additional ones (releases, environments, etc.) not listed here.

Example blueprintExample use case
GitHub Repository (githubRepository)Production Readiness scorecard
GitHub Pull Request (githubPullRequest)Delivery Performance metrics
GitHub Workflow Run (githubWorkflowRun)Measure pipeline reliability

Example team hierarchy

Below is one example of how to structure team levels, each rolling up metrics to the next. Your organization may use fewer levels or different names:

LevelBlueprintTypeMembersDescriptionExampleExample use case
1Service--Metrics calculated per service.payments-apiTrack delivery performance for a specific service.
2TeamteamUsersMetrics roll up from services to teams.payments-experienceCompare cycle time, throughput, and MTTR across teams.
3TeamgroupTeams (type: team)Rollups for cross-team comparison at scale.digital-bankingBenchmark DORA and delivery performance across a business unit or product.
4Organization-GroupsCompany-wide rollup - the single number for execs and QBR-level reporting.Acme CorpMeasure engineering health across the entire organization.
Extend freely

Add a parent_team to model deeper structures. For example: serviceteamproductbusiness unitorganization.

Prerequisites

To follow this guide, you need:

Verify your SCM integration

Before touching any blueprints, confirm your SCM integration is installed and has already created its default blueprints.

  1. Go to the Data Sources page of your portal.
  2. Confirm your SCM integration appears and its status is active.
  3. Go to the Builder page and confirm the following blueprints exist for your provider:
BlueprintIdentifierRequired for
GitHub OrganizationgithubOrganizationCore data model
GitHub TeamgithubTeamCore data model
GitHub UsergithubUserCore data model
GitHub RepositorygithubRepositoryCore data model
GitHub Pull RequestgithubPullRequestMeasure PR delivery metrics, Delivery performance scorecard, DORA metrics
GitHub WorkflowgithubWorkflowMeasure pipeline reliability
GitHub Workflow RungithubWorkflowRunMeasure pipeline reliability, Pipeline reliability scorecard
Blueprint missing after resync?

If any blueprint above is absent, trigger a manual resync of your integration - the integration recreates its default blueprints on resync. If a blueprint still doesn't appear, refer to your integration's documentation: GitHub, GitLab, Azure DevOps. If you don't need the use case listed in the Required for column, you can safely skip that blueprint.

Set up data model

You'll set up blueprints in a specific order to satisfy relation dependencies. For each blueprint below, you will either create it (if it doesn't exist yet) or edit the existing one to add the required properties and relations.

Creation order

Set up the blueprints in the order listed - each may depend on the previous one.

Core blueprints

These blueprints form the integration-agnostic core of the data model.

Set up the Organization blueprint

  1. Go to the Builder page of your portal.

  2. If an Organization blueprint already exists, click on it. Otherwise, click + Blueprint to create a new one.

  3. Click on the {...} button in the top right corner, and choose Edit JSON.

  4. Merge the following JSON definition with any existing content and click Save:

    Merge, don't replace

    If you re-run this guide after following downstream Engineering Intelligence guides (DORA, delivery performance, pipeline reliability), the organization blueprint may already hold calculation and aggregation properties those guides added. Replacing the JSON wholesale would wipe them. Merge the baseline below into whatever is already there.

    Organization blueprint (Click to expand)
    {
    "identifier": "organization",
    "title": "Organization",
    "icon": "Organization",
    "description": "A logical organization grouping teams and services",
    "schema": {
    "properties": {},
    "required": []
    }
    }

Extend the Team blueprint

The _team blueprint is a built-in Port system blueprint. You need to extend it with additional properties and relations for team hierarchy.

  1. Go to the Builder page of your portal.

  2. Find the Team blueprint and click on it.

  3. Click on the {...} button in the top right corner, and choose Edit JSON.

  4. Merge the following into the existing definition and click Save:

    Merge, don't replace

    The _team blueprint is a Port system blueprint that may already have properties and relations added by other guides or your own customizations. Replacing the JSON wholesale would wipe them. Merge only the schema, relations, and mirrorProperties fields shown below into whatever is already there.

    Team blueprint extensions (Click to expand)
    {
    "identifier": "_team",
    "schema": {
    "properties": {
    "description": { "title": "Description", "type": "string" },
    "type": {
    "title": "Type",
    "type": "string",
    "description": "Hierarchy level - team (leaf) or group (intermediate)",
    "enum": ["team", "group"],
    "enumColors": {
    "team": "blue",
    "group": "turquoise"
    },
    "default": "team"
    }
    }
    },
    "relations": {
    "parent_team": {
    "target": "_team",
    "title": "Parent Team",
    "many": false,
    "required": false
    },
    "organization": {
    "target": "organization",
    "title": "Organization",
    "many": false,
    "required": false
    }
    },
    "mirrorProperties": {
    "parent_team_name": {
    "title": "Parent Team",
    "path": "parent_team.$title"
    }
    }
    }

Set up the Service blueprint

The service blueprint represents an integration-agnostic service.
Team ownership is handled through Port's built-in $team field (declared via "ownership": { "type": "Direct" }), so the service blueprint itself does not need a team relation.
Most repository-level data (URL, README, language, last activity) is exposed via mirror properties from the linked repository blueprint, so the same fields stay in sync without duplication.

Requires repository blueprints

The service blueprint defines relations to githubRepository, gitlabRepository, and azureDevopsRepository. Each repository blueprint is created automatically by its corresponding SCM integration (see Prerequisites). Only include the relations and mirror properties for SCMs you have installed - including a relation that targets a blueprint that doesn't exist yet will cause a "target blueprint not found" error on save.

  1. Go to the Builder page of your portal.

  2. If a Service blueprint already exists, click on it. Otherwise, click + Blueprint to create a new one.

  3. Click on the {...} button in the top right corner, and choose Edit JSON.

  4. Merge the following JSON definition with any existing content and click Save:

    Merge, don't replace

    If you re-run this guide after following downstream Engineering Intelligence guides, the service blueprint may already hold calculation, aggregation, and mirror properties those guides added (e.g., DORA tier calcs, PR/MR aggregations, pipeline failure rates). Replacing the JSON wholesale would wipe them. Merge the baseline below into whatever is already there.

    Service blueprint (Click to expand)
    {
    "identifier": "service",
    "title": "Service",
    "icon": "Microservice",
    "ownership": { "type": "Direct" },
    "schema": {
    "properties": {
    "criticality": {
    "title": "Criticality",
    "icon": "Alert",
    "description": "Service criticality level",
    "type": "string",
    "enum": ["low", "medium", "high", "critical"],
    "enumColors": {
    "low": "turquoise",
    "medium": "yellow",
    "high": "orange",
    "critical": "red"
    }
    }
    },
    "required": []
    },
    "relations": {
    "github_repository": {
    "target": "githubRepository",
    "title": "GitHub repository",
    "many": false,
    "required": false
    },
    "gitlab_repository": {
    "target": "gitlabRepository",
    "title": "GitLab repository",
    "many": false,
    "required": false
    },
    "azureDevopsRepository": {
    "target": "azureDevopsRepository",
    "title": "Azure repository",
    "many": false,
    "required": false
    }
    },
    "mirrorProperties": {
    "github_repository_id": { "title": "GitHub Repository identifier", "path": "github_repository.$identifier" },
    "github_url": { "title": "GitHub URL", "path": "github_repository.url" },
    "github_readme": { "title": "GitHub README", "path": "github_repository.readme" },
    "github_codeowners": { "title": "GitHub Code Owners", "path": "github_repository.codeowners" },
    "github_description": { "title": "GitHub Description", "path": "github_repository.description" },
    "github_language": { "title": "GitHub Language", "path": "github_repository.language" },
    "github_default_branch": { "title": "GitHub Default Branch", "path": "github_repository.defaultBranch" },
    "github_last_push": { "title": "GitHub Last Push", "path": "github_repository.last_push" },
    "github_visibility": { "title": "GitHub Visibility", "path": "github_repository.visibility" },
    "github_gitignore": { "title": "GitHub .gitignore", "path": "github_repository.gitignore" },
    "github_pr_template": { "title": "GitHub PR Template", "path": "github_repository.pr_template" },
    "gitlab_repository_identifier": { "title": "GitLab Repository identifier", "path": "gitlab_repository.$identifier" },
    "gitlab_url": { "title": "GitLab URL", "path": "gitlab_repository.url" },
    "gitlab_readme": { "title": "GitLab README", "path": "gitlab_repository.readme" },
    "gitlab_codeowners": { "title": "GitLab Code Owners", "path": "gitlab_repository.codeowners" },
    "gitlab_description": { "title": "GitLab Description", "path": "gitlab_repository.description" },
    "gitlab_language": { "title": "GitLab Language", "path": "gitlab_repository.language" },
    "gitlab_default_branch": { "title": "GitLab Default Branch", "path": "gitlab_repository.defaultBranch" },
    "gitlab_last_activity": { "title": "GitLab Last Activity", "path": "gitlab_repository.last_activity" },
    "ado_repository_id": { "title": "Azure Repository identifier", "path": "azureDevopsRepository.$identifier" },
    "ado_url": { "title": "Azure URL", "path": "azureDevopsRepository.url" },
    "ado_readme": { "title": "Azure README", "path": "azureDevopsRepository.readme" },
    "ado_codeowners": { "title": "Azure Code Owners", "path": "azureDevopsRepository.codeowners" },
    "ado_last_activity": { "title": "Azure Last Activity", "path": "azureDevopsRepository.last_activity" },
    "ado_minimumApproverCount": { "title": "Minimum Approver Count", "path": "azureDevopsRepository.minimumApproverCount" }
    }
    }
Single SCM setup

If you only use one SCM, keep only that provider's relation and mirror properties. For example, a GitHub-only org keeps github_repository and the github_* mirror properties, GitLab-only or Azure DevOps-only setups follow the same pattern.

Why no team relation on service?

Port's service blueprint uses the built-in team ownership model ("ownership": { "type": "Direct" }). Each entity has a $team system field that can hold one or more teams. Aggregations on the _team blueprint use this field to roll up metrics from owned services, so you do not need a separate team relation.

SCM integration blueprints

This section configures the SCM blueprints that link the foundation layer to your repositories, teams, and users. The exact blueprints depend on which SCM(s) you have installed - select your provider below.

For each blueprint:

  1. Go to the Builder page.
  2. Find the blueprint and click on it.
  3. Click on the {...} button in the top right corner, and choose Edit JSON.
  4. Merge the JSON definition below into the existing blueprint and click Save.
Merging vs. replacing

When editing blueprints created by the integration, merge the JSON below with the existing definition - don't replace it entirely. The integration may have added properties (such as metric aggregations, calculations, or scorecards) that you want to keep. Focus on confirming the relations shown below.

The GitHub integration ships with these foundation blueprints: githubOrganization, githubTeam, githubUser, and githubRepository. The remaining blueprints (githubPullRequest, githubWorkflow, githubWorkflowRun) are configured by the use case guides that use them.

You only need to verify the relations below point to the right targets:

  • githubOrganization.organization → core organization blueprint
  • githubTeam.organizationgithubOrganization
  • githubUser.teamgithubTeam (many)
  • githubRepository.githubTeamsgithubTeam (many)
GitHub Organization blueprint (Click to expand)
{
"identifier": "githubOrganization",
"title": "GitHub Organization",
"icon": "Github",
"description": "Top-level GitHub organization - container for repositories and teams",
"schema": {
"properties": {
"login": { "title": "Organization Login", "type": "string" },
"url": { "title": "URL", "type": "string", "format": "url" },
"description": { "title": "Description", "type": "string" },
"avatarUrl": { "title": "Avatar URL", "type": "string" },
"publicRepos": { "title": "Public Repositories", "type": "number" },
"createdAt": { "title": "Created At", "type": "string", "format": "date-time" }
}
},
"relations": {
"organization": {
"target": "organization",
"title": "Organization",
"many": false,
"required": false
}
}
}
GitHub Team blueprint (Click to expand)
{
"identifier": "githubTeam",
"title": "GitHub Team",
"icon": "Github",
"schema": {
"properties": {
"slug": { "title": "Slug", "type": "string" },
"description": { "title": "Description", "type": "string" },
"link": { "title": "Link", "type": "string", "format": "url" }
}
},
"relations": {
"organization": {
"target": "githubOrganization",
"title": "Organization",
"many": false,
"required": false
}
}
}
GitHub User blueprint (Click to expand)
{
"identifier": "githubUser",
"title": "GitHub User",
"icon": "Github",
"schema": {
"properties": {
"email": { "title": "Email", "type": "string" },
"login": { "title": "Login", "type": "string" }
}
},
"relations": {
"team": {
"target": "githubTeam",
"title": "GitHub Team",
"many": true,
"required": false
}
}
}
GitHub Repository blueprint (Click to expand)

The githubRepository blueprint stays largely as the integration creates it. The link to service is on the service side (via the github_repository relation you defined above). The integration adds metric aggregations and calculations for PR throughput, cycle time, and workflow failure rates.

{
"identifier": "githubRepository",
"title": "GitHub Repository",
"icon": "Github",
"ownership": { "type": "Direct" },
"schema": {
"properties": {
"url": { "title": "Repository URL", "type": "string", "format": "url" },
"readme": { "title": "README", "type": "string", "format": "markdown" },
"codeowners": { "title": "CODEOWNERS", "type": "string", "format": "markdown" },
"defaultBranch": { "title": "Default branch", "type": "string" },
"description": { "title": "Description", "type": "string" },
"visibility": { "title": "Visibility", "type": "string" },
"language": { "title": "Language", "type": "string" },
"last_push": { "title": "Last Repository Push", "type": "string", "format": "date-time" },
"gitignore": { "title": "Git Ignore", "type": "string" },
"pr_template": { "title": "PR Template", "type": "string" }
}
},
"relations": {
"githubTeams": {
"target": "githubTeam",
"title": "GitHub Teams",
"many": true,
"required": false
}
}
}

Create the default organization, group, and team

Before you configure the integration mapping, create one Organization, one Group, and one Team entity to act as the default owners for the data the integration will ingest. You can rename or add more later, but starting with a single set of defaults keeps the setup straightforward.

  1. Navigate to the Software Catalog.
  2. Open the Organization page and click + Organization to create an entity with:
    • Identifier: default-org
    • Title: default-org
  3. Open the Team page and click + Team to create a group entity with:
    • Identifier: default-group
    • Title: default-group
    • Type: group
    • Organization: default-org
  4. Click + Team again to create a team entity with:
    • Identifier: default-team
    • Title: default-team
    • Type: team
    • Parent Team: default-group
    • Organization: leave empty - the team's organization is reachable via default-team.parent_team.organization. Setting it directly is optional and has no effect on team-level aggregations, which work via Port's $team ownership rather than the organization relation.
Mapping ingested data to your defaults

The integration mappings in the next step reference "default-org" for the relation that ties each SCM's top-level container (GitHub Organization, GitLab Namespace, or Azure Project) to the core organization blueprint. If you choose a different identifier for the default organization entity, update the mappings accordingly.

Configure integration mapping

After setting up the blueprints, configure your SCM integration's mapping so data flows into the correct blueprints and relations. Without this step, the blueprints exist but remain empty.

The mappings below are the complete EI configuration for each provider. They cover everything needed for this guide and all downstream EI guides (delivery performance, DORA, pipeline reliability): organizations, teams, users, repositories, pull/merge requests, and workflows/pipelines/builds.

Merge, don't replace

If your integration already has a custom mapping, merge these blocks into it rather than replacing the entire config. Read the existing mapping first so you don't overwrite customizations.

  1. Go to the Data Sources page of your portal.
  2. Find your SCM integration and click on it.
  3. Read the existing mapping config before making changes.
  4. Apply the complete EI mapping below for your provider:
GitHub integration mapping - complete EI configuration (Click to expand)
resources:
- kind: organization
selector:
query: "true"
port:
entity:
mappings:
identifier: .login
title: .login
blueprint: '"githubOrganization"'
properties:
login: .login
id: .id
nodeId: .node_id
url: .url
avatarUrl: .avatar_url
description: 'if .description then .description else "" end'
createdAt: .created_at
updatedAt: .updated_at
publicRepos: .public_repos
relations:
organization: '"default-org"'
- kind: team
selector:
query: "true"
members: true
port:
entity:
mappings:
identifier: .databaseId | tostring
title: .name
blueprint: '"githubTeam"'
properties:
slug: .slug
description: .description
link: .url
notification_setting: .notificationSetting
relations:
organization: '.url | capture("orgs/(?<org>[^/]+)") | .org'
- kind: user
selector:
query: "true"
port:
entity:
mappings:
identifier: .login
title: .login
blueprint: '"githubUser"'
properties:
email: .email
login: .login
- kind: team
selector:
query: "true"
members: true
port:
itemsToParse: .members.nodes
entity:
mappings:
identifier: .item.login
title: .item.login
blueprint: '"githubUser"'
relations:
team: '[.parent.id | tostring]'
- kind: repository
selector:
query: "true"
include: ["teams"]
includedFiles:
- README.md
- CODEOWNERS
- .gitignore
- .github/pull_request_template.md
port:
entity:
mappings:
identifier: .name
title: .name
blueprint: '"githubRepository"'
properties:
url: .html_url
readme: '.__includedFiles["README.md"]'
codeowners: '.__includedFiles["CODEOWNERS"]'
description: 'if .description then .description else "" end'
defaultBranch: .default_branch
language: 'if .language then .language else "" end'
last_push: .pushed_at
gitignore: '.__includedFiles[".gitignore"]'
pr_template: '.__includedFiles[".github/pull_request_template.md"]'
visibility: 'if .private then "private" else "public" end'
relations:
githubTeams: '[.__teams[].id | tostring]'
- kind: pull-request
selector:
query: "true"
maxResults: 300
since: 90
states:
- open
- closed
port:
entity:
mappings:
identifier: '.head.repo.name + "-pr-" + (.number | tostring)'
title: .title
blueprint: '"githubPullRequest"'
properties:
branch: .head.ref
closedAt: .closed_at
createdAt: .created_at
cycle_time_hours: 'if .merged_at != null and .created_at != null then ((.merged_at | fromdateiso8601) - (.created_at | fromdateiso8601)) / 3600 else null end'
has_assignees: '(.assignees | length) != 0'
has_reviewers: '(.requested_reviewers | length) != 0'
link: .html_url
mergedAt: .merged_at
prNumber: .number
status: 'if .merged_at != null then "merged" elif .state == "closed" then "closed" else "open" end'
relations:
git_hub_assignees: '[.assignees[].login]'
git_hub_creator: .user.login
git_hub_reviewers: '[.requested_reviewers[].login]'
repository: .head.repo.name
creator:
combinator: '"and"'
rules:
- property: '"git_hub_username"'
operator: '"="'
value: .user.login
reviewers:
combinator: '"and"'
rules:
- property: '"git_hub_username"'
operator: '"in"'
value: '[.requested_reviewers[]?.login // empty]'
assignees:
combinator: '"and"'
rules:
- property: '"git_hub_username"'
operator: '"in"'
value: '[.assignees[]?.login // empty]'
service:
combinator: '"and"'
rules:
- property: '"github_repository_id"'
operator: '"="'
value: .head.repo.name
- kind: workflow
selector:
query: "true"
port:
entity:
mappings:
identifier: '(.url | capture("repos/(?<repo>[^/]+/[^/]+)/") | .repo) + (.id|tostring)'
title: .name
blueprint: '"githubWorkflow"'
properties:
createdAt: .created_at
link: .html_url
path: .path
status: .state
updatedAt: .updated_at
relations:
repository: '.url | capture("repos/[^/]+/(?<repo>[^/]+)/") | .repo'
- kind: workflow-run
selector:
query: '(.head_branch | IN("main", "master", "production")) and ((.created_at | fromdateiso8601) > (now - 2592000))'
port:
entity:
mappings:
identifier: '.repository.full_name + (.id|tostring)'
title: .display_title
blueprint: '"githubWorkflowRun"'
properties:
conclusion: .conclusion
createdAt: .created_at
headBranch: .head_branch
link: .html_url
name: .name
runAttempt: .run_attempt
runNumber: .run_number
runStartedAt: .run_started_at
status: .status
triggeringActor: .triggering_actor.login
updatedAt: .updated_at
relations:
pullRequests: 'if (.pull_requests | length) > 0 then [.pull_requests[] | .head.repo.name + "-pr-" + (.number | tostring)] else null end'
repository: .repository.name
workflow: '.repository.full_name + (.workflow_id|tostring)'
service:
combinator: '"and"'
rules:
- property: '"github_repository_id"'
operator: '"="'
value: .repository.name
- kind: workflow-run
selector:
query: '(.head_branch | IN("main", "master", "production")) and ((.created_at | fromdateiso8601) > (now - 2592000))'
port:
entity:
mappings:
identifier: '.repository.full_name + (.workflow_id|tostring)'
title: '.repository.full_name + (.workflow_id|tostring)'
blueprint: '"githubWorkflow"'
properties:
last_triggered_at: .run_started_at
result: .conclusion

After saving the mapping configuration, trigger a resync of your integration to populate the catalog with data.

Verify ingestion

Once the resync completes, open the Software Catalog and confirm these entity types appear:

BlueprintWhat you should see
GitHub OrganizationOne entity per top-level GitHub organization, with the organization relation pointing to default-org.
GitHub TeamYour GitHub teams, each with organization pointing to a githubOrganization entity.
GitHub UserGitHub users, each with the team relation populated where applicable.
GitHub RepositoryYour GitHub repositories, with url, language, defaultBranch, last_push, visibility, and (where present) readme / codeowners populated.
GitHub Pull RequestPull requests with status, createdAt, mergedAt, cycle_time_hours, and has_reviewers populated. The service and repository relations link each PR to its service and repository.
GitHub WorkflowGitHub Actions workflow definitions, each linked to their repository.
GitHub Workflow RunIndividual workflow run results with conclusion, status, createdAt, and runStartedAt populated. The service, repository, and workflow relations are populated.
OrganizationThe default-org entity you created earlier, now referenced by every githubOrganization entity.
Missing entities?

If any entity type above is absent after the resync, the corresponding kind is likely not enabled in your integration mapping. Open your integration's mapping config and verify the kind is present. For example, to enable pull request ingestion for GitHub, add a pull-request block:

resources:
- kind: pull-request
selector:
query: "true"
port:
entity:
mappings:
identifier: ".id | tostring"
title: ".title"
blueprint: '"githubPullRequest"'
properties: {}
relations: {}

Refer to the full default mapping in your integration's documentation: GitHub, GitLab, Azure DevOps.

Connect services to repositories

The mappings above populate provider-specific entities (organizations/namespaces/projects, teams, users, repositories), but they do not create service entities. You decide which repositories represent services in your catalog.

For each service:

  1. Navigate to the Software Catalog.

  2. Click + Service to create a new entity (or open an existing one to edit).

  3. Set the repository relation that matches your SCM:

    • GitHub repository → matching githubRepository entity.
    • GitLab repository → matching gitlabRepository entity.
    • Azure repository → matching azureDevopsRepository entity.

    The service's repository URL, README, language, default branch, and last activity populate automatically via mirror properties.

  4. Set the Teams field (Port's built-in $team ownership) to default-team (or any team you've created).

  5. Optionally set Criticality to one of low, medium, high, or critical.

Bulk creation

You can also create services in bulk via the Port API or the Terraform provider once you have a mapping from repository to service.

What's next

With the foundational data model in place, you can now layer the Engineering Intelligence use cases on top. Each guide below assumes the core Organization, Team, and Service blueprints (with team ownership on services) plus the SCM blueprints described here are already set up.